mirror of
https://github.com/WangXuan95/Hard-PNG.git
synced 2025-01-13 20:22:52 +08:00
1955 lines
80 KiB
Systemverilog
1955 lines
80 KiB
Systemverilog
|
`timescale 1 ns/1 ns
|
||
|
|
||
|
|
||
|
|
||
|
module hard_png(
|
||
|
input wire rst,
|
||
|
input wire clk,
|
||
|
// png data input stream
|
||
|
input wire ivalid,
|
||
|
output wire iready,
|
||
|
input wire [ 7:0] ibyte,
|
||
|
// image frame configuration output
|
||
|
output wire newframe,
|
||
|
output wire [ 1:0] colortype, // 0:gray 1:gray+A 2:RGB 3:RGBA
|
||
|
output wire [13:0] width, // horizontal size / frame width / pixel per row
|
||
|
output wire [31:0] height, // vertical size / frame height / rows per frame
|
||
|
// pixel output
|
||
|
output wire ovalid,
|
||
|
output wire [ 7:0] opixelr, opixelg, opixelb, opixela
|
||
|
);
|
||
|
|
||
|
wire reset;
|
||
|
wire [13:0] bpr; // bytes per row
|
||
|
wire [ 1:0] bpp; // bytes per pixel
|
||
|
|
||
|
wire pvalid;
|
||
|
wire pready;
|
||
|
wire [ 7:0] pbyte;
|
||
|
|
||
|
wire mvalid;
|
||
|
wire [ 7:0] mbyte;
|
||
|
|
||
|
wire bvalid;
|
||
|
wire [ 7:0] bbyte;
|
||
|
|
||
|
wire isplte;
|
||
|
wire plte_wen;
|
||
|
wire [ 7:0] plte_waddr;
|
||
|
wire [23:0] plte_wdata;
|
||
|
wire [ 7:0] plte_raddr;
|
||
|
wire [23:0] plte_rdata;
|
||
|
|
||
|
assign colortype = isplte ? 2'd2 : bpp;
|
||
|
|
||
|
png_parser png_parser_i(
|
||
|
.rst ( rst ),
|
||
|
.orst ( reset ),
|
||
|
.clk ( clk ),
|
||
|
.oframe ( newframe ),
|
||
|
.isplte ( isplte ),
|
||
|
.bpp ( bpp ),
|
||
|
.ppr ( width ),
|
||
|
.bpr ( bpr ),
|
||
|
.rpf ( height ),
|
||
|
.ivalid ( ivalid ),
|
||
|
.iready ( iready ),
|
||
|
.ibyte ( ibyte ),
|
||
|
.ovalid ( pvalid ),
|
||
|
.oready ( pready ),
|
||
|
.obyte ( pbyte ),
|
||
|
.plte_wen ( plte_wen ),
|
||
|
.plte_waddr ( plte_waddr ),
|
||
|
.plte_wdata ( plte_wdata )
|
||
|
);
|
||
|
|
||
|
uz_inflate uz_inflate_i(
|
||
|
.rst ( reset ),
|
||
|
.clk ( clk ),
|
||
|
.ivalid ( pvalid ),
|
||
|
.iready ( pready ),
|
||
|
.ibyte ( pbyte ),
|
||
|
.ovalid ( mvalid ),
|
||
|
.obyte ( mbyte ),
|
||
|
.end_stream ( )
|
||
|
);
|
||
|
|
||
|
unfilter unfilter_i(
|
||
|
.rst ( reset ),
|
||
|
.clk ( clk ),
|
||
|
.bpp ( bpp ),
|
||
|
.bpr ( bpr ),
|
||
|
.ivalid ( mvalid ),
|
||
|
.idata ( mbyte ),
|
||
|
.ovalid ( bvalid ),
|
||
|
.odata ( bbyte )
|
||
|
);
|
||
|
|
||
|
build_pixel build_pixel_i(
|
||
|
.clk ( clk ),
|
||
|
.newframe ( newframe ),
|
||
|
.bpp ( bpp ),
|
||
|
.isplte ( isplte ),
|
||
|
.plte_raddr ( plte_raddr ),
|
||
|
.plte_rdata ( plte_rdata ),
|
||
|
.ivalid ( bvalid ),
|
||
|
.ibyte ( bbyte ),
|
||
|
.ovalid ( ovalid ),
|
||
|
.opixelr ( opixelr ),
|
||
|
.opixelg ( opixelg ),
|
||
|
.opixelb ( opixelb ),
|
||
|
.opixela ( opixela )
|
||
|
);
|
||
|
|
||
|
RamSinglePort #(
|
||
|
.SIZE ( 256 ),
|
||
|
.WIDTH ( 24 )
|
||
|
) ram_for_plte (
|
||
|
.clk ( clk ),
|
||
|
.wen ( plte_wen ),
|
||
|
.waddr ( 8'(plte_waddr) ),
|
||
|
.wdata ( plte_wdata ),
|
||
|
.raddr ( 8'(plte_raddr) ),
|
||
|
.rdata ( plte_rdata )
|
||
|
);
|
||
|
|
||
|
endmodule
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
module build_pixel(
|
||
|
input wire clk,
|
||
|
input wire newframe,
|
||
|
input wire [ 1:0] bpp,
|
||
|
input wire isplte,
|
||
|
output wire [ 7:0] plte_raddr,
|
||
|
input wire [23:0] plte_rdata,
|
||
|
input wire ivalid,
|
||
|
input wire [ 7:0] ibyte,
|
||
|
output reg ovalid,
|
||
|
output wire [ 7:0] opixelr, opixelg, opixelb, opixela
|
||
|
);
|
||
|
initial ovalid = 1'b0;
|
||
|
reg [1:0] pixcnt = '0;
|
||
|
reg [7:0] pr='0, pg='0, pb='0, pa='0;
|
||
|
|
||
|
assign plte_raddr = ibyte;
|
||
|
|
||
|
assign opixelr = ovalid ? (isplte ? plte_rdata[23:16] : pr) : 8'h0;
|
||
|
assign opixelg = ovalid ? (isplte ? plte_rdata[15: 8] : pg) : 8'h0;
|
||
|
assign opixelb = ovalid ? (isplte ? plte_rdata[ 7: 0] : pb) : 8'h0;
|
||
|
assign opixela = ovalid ? (isplte ? 8'hff : pa) : 8'h0;
|
||
|
|
||
|
always @ (posedge clk)
|
||
|
if(newframe) begin
|
||
|
pixcnt <= '0;
|
||
|
ovalid <= 1'b0;
|
||
|
{pr, pg, pb, pa} <= 0;
|
||
|
end else if(ivalid) begin
|
||
|
case(pixcnt)
|
||
|
2'd0 : {pr, pg, pb, pa} <= {ibyte, ibyte, ibyte, 8'hff};
|
||
|
2'd1 : { pa} <= { ibyte};
|
||
|
2'd2 : { pg, pb, pa} <= { pa, ibyte, 8'hff};
|
||
|
2'd3 : { pa} <= { ibyte};
|
||
|
endcase
|
||
|
if(pixcnt<bpp) begin
|
||
|
pixcnt <= pixcnt + 2'd1;
|
||
|
ovalid <= 1'b0;
|
||
|
end else begin
|
||
|
pixcnt <= 2'd0;
|
||
|
ovalid <= 1'b1;
|
||
|
end
|
||
|
end else
|
||
|
ovalid <= 1'b0;
|
||
|
|
||
|
endmodule
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
module png_parser(
|
||
|
input wire rst,
|
||
|
input wire clk,
|
||
|
// data input
|
||
|
input wire ivalid,
|
||
|
output reg iready,
|
||
|
input wire [ 7:0] ibyte,
|
||
|
// data output
|
||
|
output reg ovalid,
|
||
|
input wire oready,
|
||
|
output reg [ 7:0] obyte,
|
||
|
// image parameters out
|
||
|
output wire orst,
|
||
|
output reg oframe,
|
||
|
output reg isplte,
|
||
|
output reg [ 1:0] bpp, // bytes per pixel
|
||
|
output reg [13:0] ppr, // pixel per row
|
||
|
output reg [13:0] bpr, // bytes per row
|
||
|
output reg [31:0] rpf, // rows per frame
|
||
|
// PLTE RAM write port
|
||
|
output reg plte_wen,
|
||
|
output reg [ 7:0] plte_waddr,
|
||
|
output reg [23:0] plte_wdata
|
||
|
);
|
||
|
|
||
|
initial oframe = 1'b0;
|
||
|
initial isplte = 1'b0;
|
||
|
initial bpp = '0;
|
||
|
initial ppr = '0;
|
||
|
initial bpr = '0;
|
||
|
initial rpf = '0;
|
||
|
initial plte_wen = 1'b0;
|
||
|
initial plte_waddr = '0;
|
||
|
initial plte_wdata = '0;
|
||
|
|
||
|
wire ispltes [8]; assign ispltes[0]=1'b0; assign ispltes[1]=1'b0; assign ispltes[2]=1'b0; assign ispltes[3]=1'b1; assign ispltes[4]=1'b0; assign ispltes[5]=1'b0; assign ispltes[6]=1'b0; assign ispltes[7]=1'b0;
|
||
|
wire [ 1:0] bpps [8]; assign bpps[0]=2'd0; assign bpps[1]=2'd0; assign bpps[2]=2'd2; assign bpps[3]=2'd0; assign bpps[4]=2'd1; assign bpps[5]=2'd0; assign bpps[6]=2'd3; assign bpps[7]=2'd0;
|
||
|
|
||
|
wire [63:0] png_precode = 64'h89504e470d0a1a0a;
|
||
|
wire [31:0] ihdr_name = 32'h49484452;
|
||
|
wire [31:0] plte_name = 32'h504C5445;
|
||
|
wire [31:0] idat_name = 32'h49444154;
|
||
|
wire [31:0] iend_name = 32'h49454e44;
|
||
|
|
||
|
reg [ 7:0] latchbytes [7];
|
||
|
wire [ 7:0] lastbytes [8];
|
||
|
wire [63:0] lastlbytes;
|
||
|
wire [31:0] h32bit = lastlbytes[63:32];
|
||
|
wire [31:0] l32bit = lastlbytes[31: 0];
|
||
|
|
||
|
assign lastbytes[7] = ibyte;
|
||
|
|
||
|
initial {latchbytes[0],latchbytes[1],latchbytes[2],latchbytes[3],latchbytes[4],latchbytes[5],latchbytes[6]} = '0;
|
||
|
|
||
|
generate genvar ii;
|
||
|
for(ii=0; ii<7; ii++) begin : generate_latchbytes_connect
|
||
|
assign lastbytes[ii] = latchbytes[ii];
|
||
|
always @ (posedge clk or posedge rst)
|
||
|
if(rst)
|
||
|
latchbytes[ii] <= '0;
|
||
|
else begin
|
||
|
if(ivalid)
|
||
|
latchbytes[ii] <= lastbytes[ii+1];
|
||
|
end
|
||
|
end
|
||
|
endgenerate
|
||
|
|
||
|
assign lastlbytes[ 7: 0] = lastbytes[7];
|
||
|
assign lastlbytes[15: 8] = lastbytes[6];
|
||
|
assign lastlbytes[23:16] = lastbytes[5];
|
||
|
assign lastlbytes[31:24] = lastbytes[4];
|
||
|
assign lastlbytes[39:32] = lastbytes[3];
|
||
|
assign lastlbytes[47:40] = lastbytes[2];
|
||
|
assign lastlbytes[55:48] = lastbytes[1];
|
||
|
assign lastlbytes[63:56] = lastbytes[0];
|
||
|
|
||
|
reg [ 2:0] bcnt= '0;
|
||
|
reg [31:0] cnt = '0;
|
||
|
reg [ 2:0] crccnt = '0;
|
||
|
reg [ 2:0] gapcnt = '0;
|
||
|
|
||
|
enum {NONE, IHDR, PLTE, IDAT, IEND} curr_name = NONE;
|
||
|
reg busy = 1'b0;
|
||
|
reg sizevalid = 1'b0;
|
||
|
reg imagevalid = 1'b0;
|
||
|
|
||
|
reg ispltetmp = 1'b0;
|
||
|
reg [ 1:0] bpptmp = '0; // bytes per pixel
|
||
|
reg [13:0] pprtmp = '0; // pixel per row
|
||
|
reg [15:0] bprtmp = '0; // bytes per row
|
||
|
reg [31:0] rpftmp = '0; // rows per frame
|
||
|
|
||
|
reg [ 1:0] plte_bytecnt = '0;
|
||
|
reg [ 7:0] plte_pixcnt = '0;
|
||
|
|
||
|
assign orst = ~imagevalid;
|
||
|
|
||
|
wire parametervalid = ( lastbytes[7]==8'h0 &&
|
||
|
lastbytes[6]==8'h0 &&
|
||
|
lastbytes[5]==8'h0 &&
|
||
|
lastbytes[3]==8'h8 &&
|
||
|
( lastbytes[4]==8'h0 ||
|
||
|
lastbytes[4]==8'h2 ||
|
||
|
lastbytes[4]==8'h3 ||
|
||
|
lastbytes[4]==8'h4 ||
|
||
|
lastbytes[4]==8'h6
|
||
|
)
|
||
|
);
|
||
|
|
||
|
always_comb
|
||
|
if(ivalid && imagevalid && cnt>0 && curr_name==IDAT && gapcnt==2'd0) begin
|
||
|
ovalid <= 1'b1;
|
||
|
iready <= oready;
|
||
|
obyte <= ibyte;
|
||
|
end else begin
|
||
|
ovalid <= 1'b0;
|
||
|
iready <= 1'b1;
|
||
|
obyte <= '0;
|
||
|
end
|
||
|
|
||
|
always @ (posedge clk or posedge rst)
|
||
|
if(rst) begin
|
||
|
bcnt <= '0;
|
||
|
cnt <= '0;
|
||
|
crccnt <= '0;
|
||
|
gapcnt <= '0;
|
||
|
busy <= 1'b0;
|
||
|
sizevalid <= 1'b0;
|
||
|
imagevalid <= 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;
|
||
|
oframe <= 1'b0;
|
||
|
plte_wen <= 1'b0;
|
||
|
plte_waddr <= '0;
|
||
|
plte_wdata <= '0;
|
||
|
plte_bytecnt <= '0;
|
||
|
plte_pixcnt <= '0;
|
||
|
end else begin
|
||
|
oframe <= 1'b0;
|
||
|
plte_wen <= 1'b0;
|
||
|
plte_waddr <= '0;
|
||
|
plte_wdata <= '0;
|
||
|
if(ivalid) begin
|
||
|
plte_bytecnt <= '0;
|
||
|
plte_pixcnt <= '0;
|
||
|
if(~busy) begin
|
||
|
bcnt <= '0;
|
||
|
cnt <= '0;
|
||
|
crccnt <= '0;
|
||
|
busy <= (lastlbytes==png_precode);
|
||
|
end else begin
|
||
|
if(cnt>0) begin
|
||
|
bcnt <= '0;
|
||
|
if(curr_name==IHDR) begin
|
||
|
cnt <= cnt - 1;
|
||
|
gapcnt <= 2'd2;
|
||
|
if(cnt==6) begin
|
||
|
imagevalid <= 1'b0;
|
||
|
rpftmp <= l32bit;
|
||
|
if(h32bit[31:14]=='0) begin
|
||
|
sizevalid <= 1'b1;
|
||
|
pprtmp <= h32bit[13:0];
|
||
|
end else begin
|
||
|
sizevalid <= 1'b0;
|
||
|
pprtmp <= '1;
|
||
|
end
|
||
|
end else if(cnt==3) begin
|
||
|
ispltetmp <= ispltes[lastlbytes[10:8]];
|
||
|
bpptmp <= bpps[lastlbytes[10:8]];
|
||
|
end else if(cnt==2) begin
|
||
|
case(bpptmp)
|
||
|
2'd0 : bprtmp <= {2'b00, pprtmp};
|
||
|
2'd1 : bprtmp <= {1'b0, pprtmp, 1'b0};
|
||
|
2'd2 : bprtmp <= {1'b0, pprtmp, 1'b0} + {2'b00, pprtmp};
|
||
|
2'd3 : bprtmp <= {pprtmp, 2'b00};
|
||
|
endcase
|
||
|
end else if(cnt==1) begin
|
||
|
if(sizevalid && parametervalid && (bprtmp[15:14]==2'd0)) begin
|
||
|
oframe <= 1'b1;
|
||
|
imagevalid <= 1'b1;
|
||
|
isplte <= ispltetmp;
|
||
|
bpp <= bpptmp;
|
||
|
ppr <= pprtmp;
|
||
|
bpr <= bprtmp[13:0];
|
||
|
rpf <= rpftmp;
|
||
|
end else begin
|
||
|
imagevalid <= 1'b0;
|
||
|
isplte <= 1'b0;
|
||
|
bpp <= '0;
|
||
|
ppr <= '0;
|
||
|
bpr <= '0;
|
||
|
rpf <= '0;
|
||
|
end
|
||
|
end
|
||
|
end else if(curr_name==IDAT) begin
|
||
|
if(gapcnt>2'd0)
|
||
|
gapcnt <= gapcnt - 2'd1;
|
||
|
if(imagevalid && gapcnt==2'd0) begin
|
||
|
if(oready)
|
||
|
cnt <= cnt - 1;
|
||
|
end else begin
|
||
|
cnt <= cnt - 1;
|
||
|
end
|
||
|
end else if(curr_name==PLTE) begin
|
||
|
plte_pixcnt <= plte_pixcnt;
|
||
|
case(plte_bytecnt)
|
||
|
2'd0 :plte_bytecnt <= 2'd1;
|
||
|
2'd1 :plte_bytecnt <= 2'd2;
|
||
|
default:begin
|
||
|
plte_bytecnt <= 2'd0;
|
||
|
plte_pixcnt <= plte_pixcnt + 8'd1;
|
||
|
plte_wen <= 1'b1;
|
||
|
plte_waddr <= plte_pixcnt;
|
||
|
plte_wdata <= lastlbytes[23:0];
|
||
|
end
|
||
|
endcase
|
||
|
cnt <= cnt - 1;
|
||
|
end else begin
|
||
|
cnt <= cnt - 1;
|
||
|
end
|
||
|
end else if(crccnt>3'd0) begin
|
||
|
bcnt <= '0;
|
||
|
cnt <= '0;
|
||
|
crccnt <= crccnt - 3'd1;
|
||
|
if(crccnt==3'd1) begin
|
||
|
if(curr_name==IEND) begin
|
||
|
busy <= 1'b0;
|
||
|
end
|
||
|
curr_name <= NONE;
|
||
|
end
|
||
|
end else begin
|
||
|
if(bcnt==3'd7) begin
|
||
|
cnt <= h32bit;
|
||
|
crccnt <= 3'd4;
|
||
|
if (l32bit==ihdr_name)
|
||
|
curr_name <= IHDR;
|
||
|
else if(l32bit==plte_name)
|
||
|
curr_name <= PLTE;
|
||
|
else if(l32bit==idat_name)
|
||
|
curr_name <= IDAT;
|
||
|
else if(l32bit==iend_name)
|
||
|
curr_name <= IEND;
|
||
|
else
|
||
|
curr_name <= NONE;
|
||
|
end
|
||
|
bcnt <= bcnt + 3'd1;
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
endmodule
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
module uz_inflate(
|
||
|
input wire rst,
|
||
|
input wire clk,
|
||
|
input wire ivalid,
|
||
|
output reg iready,
|
||
|
input wire [7:0] ibyte,
|
||
|
output reg ovalid,
|
||
|
output reg [7:0] obyte,
|
||
|
output wire end_stream
|
||
|
);
|
||
|
|
||
|
initial ovalid = 1'b0;
|
||
|
initial obyte = '0;
|
||
|
|
||
|
wire huffman_ovalid;
|
||
|
wire [7:0] huffman_obyte;
|
||
|
reg raw_ovalid;
|
||
|
reg [7:0] raw_obyte;
|
||
|
|
||
|
reg raw_mode = 1'b0;
|
||
|
wire raw_format;
|
||
|
|
||
|
reg [ 2:0] status = '0;
|
||
|
reg [15:0] rcnt = '0;
|
||
|
reg [ 2:0] cnt = '0;
|
||
|
reg [ 7:0] rbyte = '0;
|
||
|
|
||
|
reg tvalid;
|
||
|
wire tready;
|
||
|
reg tbit;
|
||
|
|
||
|
always @ (posedge clk or posedge rst)
|
||
|
if(rst) begin
|
||
|
ovalid <= 1'b0;
|
||
|
obyte <= '0;
|
||
|
end else begin
|
||
|
if(raw_mode) begin
|
||
|
ovalid <= raw_ovalid;
|
||
|
obyte <= raw_obyte;
|
||
|
end else begin
|
||
|
ovalid <= huffman_ovalid;
|
||
|
obyte <= huffman_obyte;
|
||
|
end
|
||
|
end
|
||
|
|
||
|
always_comb
|
||
|
if(rst) begin
|
||
|
raw_ovalid <= 1'b0;
|
||
|
raw_obyte <= '0;
|
||
|
iready <= 1'b0;
|
||
|
tvalid <= 1'b0;
|
||
|
tbit <= 1'b0;
|
||
|
end else begin
|
||
|
raw_ovalid <= 1'b0;
|
||
|
raw_obyte <= '0;
|
||
|
if(raw_mode) begin
|
||
|
iready <= 1'b1;
|
||
|
tvalid <= 1'b0;
|
||
|
tbit <= 1'b0;
|
||
|
if(status>=3) begin
|
||
|
raw_ovalid <= ivalid;
|
||
|
raw_obyte <= ibyte;
|
||
|
end
|
||
|
end else begin
|
||
|
if(raw_format) begin
|
||
|
iready <= 1'b1;
|
||
|
tvalid <= 1'b0;
|
||
|
tbit <= 1'b0;
|
||
|
end else if(cnt==3'h0) begin
|
||
|
iready <= tready;
|
||
|
tvalid <= ivalid;
|
||
|
tbit <= ibyte[0];
|
||
|
end else begin
|
||
|
iready <= 1'b0;
|
||
|
tvalid <= 1'b1;
|
||
|
tbit <= rbyte[cnt];
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
always @ (posedge clk or posedge rst)
|
||
|
if(rst) begin
|
||
|
raw_mode <= 1'b0;
|
||
|
cnt <= '0;
|
||
|
rbyte <= '0;
|
||
|
rcnt <= '0;
|
||
|
status <= '0;
|
||
|
end else begin
|
||
|
if(raw_mode) begin
|
||
|
cnt <= '0;
|
||
|
rbyte <= '0;
|
||
|
if(ivalid) begin
|
||
|
if (status==0) begin
|
||
|
rcnt[15:8] <= ibyte;
|
||
|
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
|
||
|
rcnt <= '0;
|
||
|
status <= '0;
|
||
|
if(raw_format) begin
|
||
|
if(ivalid) begin
|
||
|
raw_mode <= 1'b1;
|
||
|
rcnt[ 7:0] <= ibyte;
|
||
|
end
|
||
|
cnt <= '0;
|
||
|
rbyte <= '0;
|
||
|
end else begin
|
||
|
if(cnt==3'h0) begin
|
||
|
if(ivalid & tready) begin
|
||
|
cnt <= cnt + 3'h1;
|
||
|
rbyte <= ibyte;
|
||
|
end
|
||
|
end else begin
|
||
|
if(tready)
|
||
|
cnt <= cnt + 3'h1;
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
|
||
|
huffman_inflate huffman_inflate_i(
|
||
|
.rst ( raw_mode | rst ),
|
||
|
.clk ( clk ),
|
||
|
.ivalid ( tvalid ),
|
||
|
.iready ( tready ),
|
||
|
.ibit ( tbit ),
|
||
|
.ovalid ( huffman_ovalid ),
|
||
|
.obyte ( huffman_obyte ),
|
||
|
.raw_format ( raw_format ),
|
||
|
.end_stream ( end_stream )
|
||
|
);
|
||
|
|
||
|
endmodule
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
module huffman_inflate(
|
||
|
input wire rst,
|
||
|
input wire clk,
|
||
|
input wire ivalid,
|
||
|
output wire iready,
|
||
|
input wire ibit,
|
||
|
output wire ovalid,
|
||
|
output wire [7:0] obyte,
|
||
|
output reg raw_format,
|
||
|
output reg end_stream
|
||
|
);
|
||
|
|
||
|
initial {raw_format, end_stream} = '0;
|
||
|
|
||
|
wire [ 4:0] CLCL [19]; assign CLCL[0]=5'd16; assign CLCL[1]=5'd17; assign CLCL[2]=5'd18; assign CLCL[3]=5'd0; assign CLCL[4]=5'd8; assign CLCL[5]=5'd7; assign CLCL[6]=5'd9; assign CLCL[7]=5'd6; assign CLCL[8]=5'd10; assign CLCL[9]=5'd5; assign CLCL[10]=5'd11; assign CLCL[11]=5'd4; assign CLCL[12]=5'd12; assign CLCL[13]=5'd3; assign CLCL[14]=5'd13; assign CLCL[15]=5'd2; assign CLCL[16]=5'd14; assign CLCL[17]=5'd1; assign CLCL[18]=5'd15;
|
||
|
wire [ 8:0] LENGTH_BASE [30]; assign LENGTH_BASE[0]=9'd0; assign LENGTH_BASE[1]=9'd3; assign LENGTH_BASE[2]=9'd4; assign LENGTH_BASE[3]=9'd5; assign LENGTH_BASE[4]=9'd6; assign LENGTH_BASE[5]=9'd7; assign LENGTH_BASE[6]=9'd8; assign LENGTH_BASE[7]=9'd9; assign LENGTH_BASE[8]=9'd10; assign LENGTH_BASE[9]=9'd11; assign LENGTH_BASE[10]=9'd13; assign LENGTH_BASE[11]=9'd15; assign LENGTH_BASE[12]=9'd17; assign LENGTH_BASE[13]=9'd19; assign LENGTH_BASE[14]=9'd23; assign LENGTH_BASE[15]=9'd27; assign LENGTH_BASE[16]=9'd31; assign LENGTH_BASE[17]=9'd35; assign LENGTH_BASE[18]=9'd43; assign LENGTH_BASE[19]=9'd51; assign LENGTH_BASE[20]=9'd59; assign LENGTH_BASE[21]=9'd67; assign LENGTH_BASE[22]=9'd83; assign LENGTH_BASE[23]=9'd99; assign LENGTH_BASE[24]=9'd115; assign LENGTH_BASE[25]=9'd131; assign LENGTH_BASE[26]=9'd163; assign LENGTH_BASE[27]=9'd195; assign LENGTH_BASE[28]=9'd227; assign LENGTH_BASE[29]=9'd258;
|
||
|
wire [ 2:0] LENGTH_EXTRA [30]; assign LENGTH_EXTRA[0]=3'd0; assign LENGTH_EXTRA[1]=3'd0; assign LENGTH_EXTRA[2]=3'd0; assign LENGTH_EXTRA[3]=3'd0; assign LENGTH_EXTRA[4]=3'd0; assign LENGTH_EXTRA[5]=3'd0; assign LENGTH_EXTRA[6]=3'd0; assign LENGTH_EXTRA[7]=3'd0; assign LENGTH_EXTRA[8]=3'd0; assign LENGTH_EXTRA[9]=3'd1; assign LENGTH_EXTRA[10]=3'd1; assign LENGTH_EXTRA[11]=3'd1; assign LENGTH_EXTRA[12]=3'd1; assign LENGTH_EXTRA[13]=3'd2; assign LENGTH_EXTRA[14]=3'd2; assign LENGTH_EXTRA[15]=3'd2; assign LENGTH_EXTRA[16]=3'd2; assign LENGTH_EXTRA[17]=3'd3; assign LENGTH_EXTRA[18]=3'd3; assign LENGTH_EXTRA[19]=3'd3; assign LENGTH_EXTRA[20]=3'd3; assign LENGTH_EXTRA[21]=3'd4; assign LENGTH_EXTRA[22]=3'd4; assign LENGTH_EXTRA[23]=3'd4; assign LENGTH_EXTRA[24]=3'd4; assign LENGTH_EXTRA[25]=3'd5; assign LENGTH_EXTRA[26]=3'd5; assign LENGTH_EXTRA[27]=3'd5; assign LENGTH_EXTRA[28]=3'd5; assign LENGTH_EXTRA[29]=3'd0;
|
||
|
wire [14:0] DISTANCE_BASE [30]; assign DISTANCE_BASE[0]=15'd1; assign DISTANCE_BASE[1]=15'd2; assign DISTANCE_BASE[2]=15'd3; assign DISTANCE_BASE[3]=15'd4; assign DISTANCE_BASE[4]=15'd5; assign DISTANCE_BASE[5]=15'd7; assign DISTANCE_BASE[6]=15'd9; assign DISTANCE_BASE[7]=15'd13; assign DISTANCE_BASE[8]=15'd17; assign DISTANCE_BASE[9]=15'd25; assign DISTANCE_BASE[10]=15'd33; assign DISTANCE_BASE[11]=15'd49; assign DISTANCE_BASE[12]=15'd65; assign DISTANCE_BASE[13]=15'd97; assign DISTANCE_BASE[14]=15'd129; assign DISTANCE_BASE[15]=15'd193; assign DISTANCE_BASE[16]=15'd257; assign DISTANCE_BASE[17]=15'd385; assign DISTANCE_BASE[18]=15'd513; assign DISTANCE_BASE[19]=15'd769; assign DISTANCE_BASE[20]=15'd1025; assign DISTANCE_BASE[21]=15'd1537; assign DISTANCE_BASE[22]=15'd2049; assign DISTANCE_BASE[23]=15'd3073; assign DISTANCE_BASE[24]=15'd4097; assign DISTANCE_BASE[25]=15'd6145; assign DISTANCE_BASE[26]=15'd8193; assign DISTANCE_BASE[27]=15'd12289; assign DISTANCE_BASE[28]=15'd16385; assign DISTANCE_BASE[29]=15'd24577;
|
||
|
wire [ 3:0] DISTANCE_EXTRA [30]; assign DISTANCE_EXTRA[0]=4'd0; assign DISTANCE_EXTRA[1]=4'd0; assign DISTANCE_EXTRA[2]=4'd0; assign DISTANCE_EXTRA[3]=4'd0; assign DISTANCE_EXTRA[4]=4'd1; assign DISTANCE_EXTRA[5]=4'd1; assign DISTANCE_EXTRA[6]=4'd2; assign DISTANCE_EXTRA[7]=4'd2; assign DISTANCE_EXTRA[8]=4'd3; assign DISTANCE_EXTRA[9]=4'd3; assign DISTANCE_EXTRA[10]=4'd4; assign DISTANCE_EXTRA[11]=4'd4; assign DISTANCE_EXTRA[12]=4'd5; assign DISTANCE_EXTRA[13]=4'd5; assign DISTANCE_EXTRA[14]=4'd6; assign DISTANCE_EXTRA[15]=4'd6; assign DISTANCE_EXTRA[16]=4'd7; assign DISTANCE_EXTRA[17]=4'd7; assign DISTANCE_EXTRA[18]=4'd8; assign DISTANCE_EXTRA[19]=4'd8; assign DISTANCE_EXTRA[20]=4'd9; assign DISTANCE_EXTRA[21]=4'd9; assign DISTANCE_EXTRA[22]=4'd10; assign DISTANCE_EXTRA[23]=4'd10; assign DISTANCE_EXTRA[24]=4'd11; assign DISTANCE_EXTRA[25]=4'd11; assign DISTANCE_EXTRA[26]=4'd12; assign DISTANCE_EXTRA[27]=4'd12; assign DISTANCE_EXTRA[28]=4'd13; assign DISTANCE_EXTRA[29]=4'd13;
|
||
|
|
||
|
reg irepeat = 1'b0;
|
||
|
reg srepeat = 1'b0;
|
||
|
|
||
|
reg symbol_valid = 1'b0;
|
||
|
reg [7:0] symbol = '0;
|
||
|
|
||
|
reg decoder_nreset = 1'b0;
|
||
|
|
||
|
reg [ 1:0] iword = '0;
|
||
|
reg [ 1:0] ibcnt = '0;
|
||
|
reg [ 4:0] precode_wpt = '0;
|
||
|
|
||
|
reg bfin = 1'b0;
|
||
|
reg bfix = 1'b0;
|
||
|
reg fixed_tree = 1'b0;
|
||
|
reg [13:0] precode_reg = '0;
|
||
|
wire [ 4:0] hclen = 5'd4 + {1'b0, precode_reg[13:10]};
|
||
|
wire [ 8:0] hlit = 9'd257 + precode_reg[ 4: 0];
|
||
|
wire [ 8:0] hdist = 9'd1 + {4'h0, precode_reg[ 9: 5]};
|
||
|
wire [ 8:0] hmax = hlit + hdist;
|
||
|
wire [ 8:0] hend = (hlit+9'd32>9'd288) ? hlit+9'd32 : 9'd288;
|
||
|
|
||
|
reg [ 4:0] lentree_wpt = '0;
|
||
|
reg [ 8:0] tree_wpt = '0;
|
||
|
|
||
|
wire lentree_codeen;
|
||
|
wire [ 5:0] lentree_code;
|
||
|
wire codetree_codeen;
|
||
|
wire [ 9:0] codetree_code;
|
||
|
wire distree_codeen;
|
||
|
wire [ 9:0] distree_code;
|
||
|
|
||
|
reg [ 2:0] repeat_code_pt = '0;
|
||
|
enum {REPEAT_NONE, REPEAT_PREVIOUS, REPEAT_ZERO_FEW, REPEAT_ZERO_MANY} repeat_mode = REPEAT_NONE;
|
||
|
reg [ 6:0] repeat_code='0;
|
||
|
reg [ 7:0] repeat_len ='0;
|
||
|
reg [ 5:0] repeat_val = '0;
|
||
|
|
||
|
reg lentree_run = 1'b0;
|
||
|
wire lentree_done;
|
||
|
reg tree_run = 1'b0;
|
||
|
wire codetree_done;
|
||
|
wire distree_done;
|
||
|
wire tree_done = (codetree_done & distree_done) | fixed_tree;
|
||
|
|
||
|
reg [ 2:0] tcnt =3'h0, tmax =3'h0;
|
||
|
reg [ 3:0] dscnt=4'h0, dsmax=4'h0;
|
||
|
|
||
|
enum {T, D, R, S} status = T;
|
||
|
|
||
|
wire lentree_ien = ~end_stream & ~raw_format & ivalid & lentree_done & ~lentree_codeen & (repeat_mode==REPEAT_NONE && repeat_len==8'd0) & (tree_wpt<hmax);
|
||
|
wire codetree_ien = ~end_stream & ~raw_format & ivalid & tree_done & ~codetree_codeen & (tcnt==3'd0) & (dscnt==4'd0) & (status==T);
|
||
|
wire distree_ien = ~end_stream & ~raw_format & ivalid & tree_done & ~distree_codeen & (tcnt==3'd0) & (dscnt==4'd0) & (status==D);
|
||
|
|
||
|
assign iready = end_stream | (~raw_format & (
|
||
|
( precode_wpt<17 || lentree_wpt<hclen ) |
|
||
|
( 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 & (status==T || status==D || (status==R && dscnt>4'd0)) ) ) );
|
||
|
|
||
|
reg [ 8:0] lengthb= '0;
|
||
|
reg [ 5:0] lengthe= '0;
|
||
|
wire [ 8:0] length = lengthb + lengthe;
|
||
|
reg [ 8:0] len_last = '0;
|
||
|
|
||
|
reg [15:0] distanceb='0;
|
||
|
reg [15:0] distancee='0;
|
||
|
wire [15:0] distance = distanceb + distancee;
|
||
|
|
||
|
reg lentree_wen = 1'b0;
|
||
|
reg [ 4:0] lentree_waddr = '0;
|
||
|
reg [ 2:0] lentree_wdata = '0;
|
||
|
reg codetree_wen = 1'b0;
|
||
|
reg [ 8:0] codetree_waddr = '0;
|
||
|
reg [ 5:0] codetree_wdata = '0;
|
||
|
reg distree_wen = 1'b0;
|
||
|
reg [ 4:0] distree_waddr = '0;
|
||
|
reg [ 5:0] distree_wdata = '0;
|
||
|
|
||
|
wire [ 5:0] lentree_raddr;
|
||
|
wire [ 5:0] lentree_rdata;
|
||
|
wire [ 9:0] codetree_raddr;
|
||
|
wire [ 9:0] codetree_rdata, codetree_rdata_fixed;
|
||
|
wire [ 5:0] distree_raddr;
|
||
|
wire [ 9:0] distree_rdata, distree_rdata_fixed;
|
||
|
|
||
|
task automatic lentree_write(input wen=1'b0, input [4:0] waddr='0, input [2:0] wdata='0);
|
||
|
lentree_wen <= wen;
|
||
|
lentree_waddr <= waddr;
|
||
|
lentree_wdata <= wdata;
|
||
|
endtask
|
||
|
|
||
|
task automatic codetree_write(input wen=1'b0, input [8:0] waddr='0, input [5:0] wdata='0);
|
||
|
codetree_wen <= wen;
|
||
|
codetree_waddr <= waddr;
|
||
|
codetree_wdata <= wdata;
|
||
|
endtask
|
||
|
|
||
|
task automatic distree_write(input wen=1'b0, input [4:0] waddr='0, input [5:0] wdata='0);
|
||
|
distree_wen <= wen;
|
||
|
distree_waddr <= waddr;
|
||
|
distree_wdata <= wdata;
|
||
|
endtask
|
||
|
|
||
|
task automatic reset_all_regs();
|
||
|
decoder_nreset <= 1'b0;
|
||
|
{bfin, bfix, fixed_tree} <= '0;
|
||
|
iword <= '0;
|
||
|
ibcnt <= '0;
|
||
|
precode_wpt <= '0;
|
||
|
precode_reg <= '0;
|
||
|
lentree_wpt <= '0;
|
||
|
lentree_run <= 1'b0;
|
||
|
tree_run <= 1'b0;
|
||
|
lentree_write();
|
||
|
codetree_write();
|
||
|
distree_write();
|
||
|
repeat_code_pt <= '0;
|
||
|
repeat_mode <= REPEAT_NONE;
|
||
|
repeat_code <= '0;
|
||
|
repeat_len <= '0;
|
||
|
repeat_val <= '0;
|
||
|
tree_wpt <= '0;
|
||
|
tcnt <= '0;
|
||
|
tmax <= '0;
|
||
|
lengthb <= '0;
|
||
|
lengthe <= '0;
|
||
|
distanceb<= '0;
|
||
|
distancee<= '0;
|
||
|
dscnt <= '0;
|
||
|
dsmax <= '0;
|
||
|
status <= T;
|
||
|
symbol_valid <= 1'b0;
|
||
|
symbol <= '0;
|
||
|
irepeat <= 1'b0;
|
||
|
srepeat <= 1'b0;
|
||
|
len_last <= '0;
|
||
|
endtask
|
||
|
|
||
|
always @ (posedge clk or posedge rst)
|
||
|
if(rst) begin
|
||
|
{raw_format, end_stream} <= '0;
|
||
|
reset_all_regs();
|
||
|
end else begin
|
||
|
symbol_valid <= 1'b0;
|
||
|
symbol <= '0;
|
||
|
irepeat <= 1'b0;
|
||
|
srepeat <= 1'b0;
|
||
|
decoder_nreset <= 1'b1;
|
||
|
lentree_write();
|
||
|
codetree_write();
|
||
|
distree_write();
|
||
|
if(precode_wpt<=2) begin
|
||
|
lentree_run <= 1'b0;
|
||
|
tree_run <= 1'b0;
|
||
|
if(ivalid) begin
|
||
|
precode_wpt <= precode_wpt + 5'd1;
|
||
|
if(precode_wpt==0) begin
|
||
|
bfin <= ibit;
|
||
|
end else if(precode_wpt==1) begin
|
||
|
bfix <= ibit;
|
||
|
end else begin
|
||
|
case({ibit,bfix})
|
||
|
2'b00 :
|
||
|
raw_format <= 1'b1;
|
||
|
2'b01 : begin
|
||
|
precode_wpt <= '1;
|
||
|
lentree_wpt <= '1;
|
||
|
tree_wpt <= '1;
|
||
|
fixed_tree <= 1'b1;
|
||
|
end
|
||
|
endcase
|
||
|
end
|
||
|
end
|
||
|
end else if(precode_wpt<17) begin
|
||
|
lentree_run <= 1'b0;
|
||
|
tree_run <= 1'b0;
|
||
|
if(ivalid) begin
|
||
|
precode_reg <= {ibit, precode_reg[13:1]};
|
||
|
precode_wpt <= precode_wpt + 5'd1;
|
||
|
end
|
||
|
end else if(lentree_wpt<hclen) begin
|
||
|
lentree_run <= 1'b0;
|
||
|
tree_run <= 1'b0;
|
||
|
if(ivalid) begin
|
||
|
if(ibcnt<2'd2) begin
|
||
|
iword[ibcnt[0]] <= ibit;
|
||
|
ibcnt <= ibcnt + 2'd1;
|
||
|
end else begin
|
||
|
lentree_write(1'b1, CLCL[lentree_wpt], {ibit, iword});
|
||
|
ibcnt <= 2'd0;
|
||
|
lentree_wpt <= lentree_wpt + 5'd1;
|
||
|
end
|
||
|
end
|
||
|
end else if(lentree_wpt<19) begin
|
||
|
lentree_run <= 1'b0;
|
||
|
tree_run <= 1'b0;
|
||
|
lentree_write(1'b1, CLCL[lentree_wpt], '0);
|
||
|
lentree_wpt <= lentree_wpt + 5'd1;
|
||
|
end else if(~ (lentree_done | fixed_tree)) begin
|
||
|
lentree_run <= ~fixed_tree;
|
||
|
tree_run <= 1'b0;
|
||
|
end else if(tree_wpt<hmax) begin
|
||
|
lentree_run <= ~fixed_tree;
|
||
|
tree_run <= 1'b0;
|
||
|
if(repeat_code_pt>3'd0) begin
|
||
|
if(ivalid) begin
|
||
|
repeat_code_pt <= repeat_code_pt - 3'd1;
|
||
|
repeat_code[3'd7-repeat_code_pt] <= ibit;
|
||
|
end
|
||
|
end else if(repeat_mode>0) begin
|
||
|
case(repeat_mode)
|
||
|
REPEAT_PREVIOUS: begin
|
||
|
repeat_len <= repeat_code[6:5] + 8'd3;
|
||
|
end
|
||
|
REPEAT_ZERO_FEW: begin
|
||
|
repeat_len <= repeat_code[6:4] + 8'd3;
|
||
|
end
|
||
|
REPEAT_ZERO_MANY: begin
|
||
|
repeat_len <= repeat_code[6:0] + 8'd11;
|
||
|
end
|
||
|
default: begin
|
||
|
repeat_len <= 0;
|
||
|
end
|
||
|
endcase
|
||
|
repeat_mode <= REPEAT_NONE;
|
||
|
end else if(repeat_len>8'd0) begin
|
||
|
repeat_len <= repeat_len - 8'd1;
|
||
|
tree_wpt <= tree_wpt + 9'd1;
|
||
|
if(tree_wpt<288)
|
||
|
codetree_write(1'b1, tree_wpt, (tree_wpt<hlit) ? repeat_val : '0);
|
||
|
if(tree_wpt>=hlit && tree_wpt<(hlit+9'd32))
|
||
|
distree_write(1'b1, tree_wpt - hlit, (tree_wpt<hmax) ? repeat_val : '0);
|
||
|
end else if(lentree_codeen) begin
|
||
|
case(lentree_code)
|
||
|
16: begin // repeat previous
|
||
|
repeat_mode <= REPEAT_PREVIOUS;
|
||
|
repeat_code_pt <= 3'd2;
|
||
|
end
|
||
|
17: begin // repeat 0 for 3-10 times
|
||
|
repeat_mode <= REPEAT_ZERO_FEW;
|
||
|
repeat_val <= 0;
|
||
|
repeat_code_pt <= 3'd3;
|
||
|
end
|
||
|
18: begin // repeat 0 for 11-138 times
|
||
|
repeat_mode <= REPEAT_ZERO_MANY;
|
||
|
repeat_val <= 0;
|
||
|
repeat_code_pt <= 3'd7;
|
||
|
end
|
||
|
default: begin // normal value
|
||
|
repeat_mode <= REPEAT_NONE;
|
||
|
repeat_val <= lentree_code; // save previous code for repeat
|
||
|
repeat_code_pt <= 3'd0;
|
||
|
tree_wpt <= tree_wpt + 9'd1;
|
||
|
if(tree_wpt<288)
|
||
|
codetree_write(1'b1, tree_wpt, (tree_wpt<hlit) ? lentree_code : '0);
|
||
|
if(tree_wpt>=hlit && tree_wpt<(hlit+9'd32))
|
||
|
distree_write(1'b1, tree_wpt - hlit, (tree_wpt<hmax) ? lentree_code : '0);
|
||
|
end
|
||
|
endcase
|
||
|
repeat_code <= '0;
|
||
|
end
|
||
|
end else if(tree_wpt<hend) begin
|
||
|
lentree_run <= ~fixed_tree;
|
||
|
tree_run <= 1'b0;
|
||
|
if(tree_wpt<288)
|
||
|
codetree_write(1'b1, tree_wpt, '0);
|
||
|
if(tree_wpt>=hlit && tree_wpt<(hlit+9'd32))
|
||
|
distree_write(1'b1, tree_wpt - hlit, '0);
|
||
|
tree_wpt <= tree_wpt + 9'd1;
|
||
|
end else if(tree_wpt<hend+2) begin
|
||
|
lentree_run <= ~fixed_tree;
|
||
|
tree_run <= 1'b0;
|
||
|
tree_wpt <= tree_wpt + 9'd1;
|
||
|
end else if(~tree_done) begin
|
||
|
lentree_run <= ~fixed_tree;
|
||
|
tree_run <= 1'b1;
|
||
|
end else begin
|
||
|
lentree_run <= ~fixed_tree;
|
||
|
tree_run <= ~fixed_tree;
|
||
|
if(dscnt>4'd0) begin
|
||
|
if(ivalid) begin
|
||
|
dscnt <= dscnt - 4'd1;
|
||
|
distancee[dsmax-dscnt] <= ibit;
|
||
|
end
|
||
|
end else if(tcnt>3'd0) begin
|
||
|
if(ivalid) begin
|
||
|
tcnt <= tcnt - 3'd1;
|
||
|
lengthe[tmax-tcnt] <= ibit;
|
||
|
end
|
||
|
end else if(status==R) begin
|
||
|
status <= S;
|
||
|
len_last <= length;
|
||
|
srepeat <= 1'b1;
|
||
|
end else if(status==S) begin
|
||
|
if(len_last>0) begin
|
||
|
irepeat <= 1'b1;
|
||
|
len_last <= len_last - 9'd1;
|
||
|
end else
|
||
|
status <= T;
|
||
|
end else if(codetree_codeen) begin
|
||
|
if(codetree_code<10'd256) begin // normal symbol
|
||
|
symbol_valid <= 1'b1;
|
||
|
symbol <= codetree_code[7:0];
|
||
|
end else if(codetree_code==10'd256) begin // end symbol
|
||
|
end_stream <= bfin;
|
||
|
reset_all_regs();
|
||
|
end else begin // special symbol
|
||
|
lengthb<= LENGTH_BASE[codetree_code-10'd256];
|
||
|
lengthe<= '0;
|
||
|
tcnt <= LENGTH_EXTRA[codetree_code-10'd256];
|
||
|
tmax <= LENGTH_EXTRA[codetree_code-10'd256];
|
||
|
status <= D;
|
||
|
end
|
||
|
end else if(distree_codeen) begin
|
||
|
distanceb<= DISTANCE_BASE[distree_code];
|
||
|
distancee<= '0;
|
||
|
dscnt <= DISTANCE_EXTRA[distree_code];
|
||
|
dsmax <= DISTANCE_EXTRA[distree_code];
|
||
|
status <= R;
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
huffman_build #(
|
||
|
.NUMCODES ( 19 ),
|
||
|
.CODEBITS ( 3 ),
|
||
|
.BITLENGTH ( 7 ),
|
||
|
.OUTWIDTH ( 6 )
|
||
|
) lentree_builder (
|
||
|
.clk ( clk ),
|
||
|
.wren ( lentree_wen ),
|
||
|
.wraddr ( lentree_waddr ),
|
||
|
.wrdata ( lentree_wdata ),
|
||
|
.run ( lentree_run ),
|
||
|
.done ( lentree_done ),
|
||
|
.rdaddr ( lentree_raddr ),
|
||
|
.rddata ( lentree_rdata )
|
||
|
);
|
||
|
|
||
|
huffman_decode_symbol #(
|
||
|
.NUMCODES ( 19 ),
|
||
|
.OUTWIDTH ( 6 )
|
||
|
) lentree_decoder (
|
||
|
.rst ( ~decoder_nreset),
|
||
|
.clk ( clk ),
|
||
|
.ien ( lentree_ien ),
|
||
|
.ibit ( ibit ),
|
||
|
.oen ( lentree_codeen ),
|
||
|
.ocode ( lentree_code ),
|
||
|
.rdaddr ( lentree_raddr ),
|
||
|
.rddata ( lentree_rdata )
|
||
|
);
|
||
|
|
||
|
huffman_build #(
|
||
|
.NUMCODES ( 288 ),
|
||
|
.CODEBITS ( 5 ),
|
||
|
.BITLENGTH ( 15 ),
|
||
|
.OUTWIDTH ( 10 )
|
||
|
) codetree_builder (
|
||
|
.clk ( clk ),
|
||
|
.wren ( codetree_wen ),
|
||
|
.wraddr ( codetree_waddr ),
|
||
|
.wrdata ( (5)'(codetree_wdata) ),
|
||
|
.run ( tree_run ),
|
||
|
.done ( codetree_done ),
|
||
|
.rdaddr ( codetree_raddr ),
|
||
|
.rddata ( codetree_rdata )
|
||
|
);
|
||
|
|
||
|
fixed_codetree codetree_fixed(
|
||
|
.clk ( clk ),
|
||
|
.rdaddr ( codetree_raddr ),
|
||
|
.rddata ( codetree_rdata_fixed )
|
||
|
);
|
||
|
|
||
|
huffman_decode_symbol #(
|
||
|
.NUMCODES ( 288 ),
|
||
|
.OUTWIDTH ( 10 )
|
||
|
) codetree_decoder (
|
||
|
.rst ( ~decoder_nreset),
|
||
|
.clk ( clk ),
|
||
|
.ien ( codetree_ien ),
|
||
|
.ibit ( ibit ),
|
||
|
.oen ( codetree_codeen),
|
||
|
.ocode ( codetree_code ),
|
||
|
.rdaddr ( codetree_raddr ),
|
||
|
.rddata ( fixed_tree ? codetree_rdata_fixed : codetree_rdata )
|
||
|
);
|
||
|
|
||
|
huffman_build #(
|
||
|
.NUMCODES ( 32 ),
|
||
|
.CODEBITS ( 5 ),
|
||
|
.BITLENGTH ( 15 ),
|
||
|
.OUTWIDTH ( 10 )
|
||
|
) distree_builder (
|
||
|
.clk ( clk ),
|
||
|
.wren ( distree_wen ),
|
||
|
.wraddr ( distree_waddr ),
|
||
|
.wrdata ( (5)'(distree_wdata) ),
|
||
|
.run ( tree_run ),
|
||
|
.done ( distree_done ),
|
||
|
.rdaddr ( distree_raddr ),
|
||
|
.rddata ( distree_rdata )
|
||
|
);
|
||
|
|
||
|
fixed_distree distree_fixed(
|
||
|
.clk ( clk ),
|
||
|
.rdaddr ( distree_raddr ),
|
||
|
.rddata ( distree_rdata_fixed )
|
||
|
);
|
||
|
|
||
|
huffman_decode_symbol #(
|
||
|
.NUMCODES ( 32 ),
|
||
|
.OUTWIDTH ( 10 )
|
||
|
) distree_decoder (
|
||
|
.rst ( ~decoder_nreset),
|
||
|
.clk ( clk ),
|
||
|
.ien ( distree_ien ),
|
||
|
.ibit ( ibit ),
|
||
|
.oen ( distree_codeen ),
|
||
|
.ocode ( distree_code ),
|
||
|
.rdaddr ( distree_raddr ),
|
||
|
.rddata ( fixed_tree ? distree_rdata_fixed : distree_rdata )
|
||
|
);
|
||
|
|
||
|
repeat_buffer repeat_buffer_i(
|
||
|
.clk ( clk ),
|
||
|
|
||
|
.ivalid ( symbol_valid ),
|
||
|
.idata ( symbol ),
|
||
|
|
||
|
.repeat_en ( irepeat ),
|
||
|
.repeat_start ( srepeat ),
|
||
|
.repeat_dist ( distance ),
|
||
|
|
||
|
.ovalid ( ovalid ),
|
||
|
.odata ( obyte )
|
||
|
);
|
||
|
|
||
|
endmodule
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
module huffman_decode_symbol #(
|
||
|
parameter NUMCODES = 288,
|
||
|
parameter OUTWIDTH = 10
|
||
|
)(
|
||
|
rst, clk,
|
||
|
ien, ibit,
|
||
|
oen, ocode,
|
||
|
rdaddr, rddata
|
||
|
);
|
||
|
|
||
|
function automatic integer clogb2(input integer val);
|
||
|
integer valtmp;
|
||
|
valtmp = val;
|
||
|
for(clogb2=0; valtmp>0; clogb2=clogb2+1) valtmp = valtmp>>1;
|
||
|
endfunction
|
||
|
|
||
|
input rst, clk;
|
||
|
input ien, ibit;
|
||
|
output oen = 1'b0;
|
||
|
output [ OUTWIDTH-1:0] ocode = '0;
|
||
|
output [clogb2(2*NUMCODES-1)-1:0] rdaddr;
|
||
|
input [ OUTWIDTH-1:0] rddata;
|
||
|
|
||
|
wire rst, clk;
|
||
|
wire ien, ibit;
|
||
|
reg oen = 1'b0;
|
||
|
reg [ OUTWIDTH-1:0] ocode = '0;
|
||
|
wire [clogb2(2*NUMCODES-1)-1:0] rdaddr;
|
||
|
wire [ OUTWIDTH-1:0] rddata;
|
||
|
|
||
|
reg [clogb2(2*NUMCODES-1)-2:0] tpos = '0;
|
||
|
wire [clogb2(2*NUMCODES-1)-2:0] ntpos;
|
||
|
reg ienl = 1'b0;
|
||
|
|
||
|
assign rdaddr = {ntpos, ibit};
|
||
|
|
||
|
assign ntpos = ienl ? (clogb2(2*NUMCODES-1)-1)'(rddata<(OUTWIDTH)'(NUMCODES) ? '0 : rddata-(OUTWIDTH)'(NUMCODES)) : tpos;
|
||
|
|
||
|
always @ (posedge clk or posedge rst)
|
||
|
if(rst)
|
||
|
ienl <= 1'b0;
|
||
|
else
|
||
|
ienl <= ien;
|
||
|
|
||
|
always @ (posedge clk or posedge rst)
|
||
|
if(rst)
|
||
|
tpos <= '0;
|
||
|
else
|
||
|
tpos <= ntpos;
|
||
|
|
||
|
always_comb
|
||
|
if(ienl && rddata<NUMCODES) begin
|
||
|
oen <= 1'b1;
|
||
|
ocode <= rddata;
|
||
|
end else begin
|
||
|
oen <= 1'b0;
|
||
|
ocode <= '0;
|
||
|
end
|
||
|
|
||
|
endmodule
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
module fixed_codetree (
|
||
|
input logic clk,
|
||
|
input logic [9:0] rdaddr,
|
||
|
output logic [9:0] rddata
|
||
|
);
|
||
|
|
||
|
wire [9:0] rom [1024]; assign rom[0]=10'd289; assign rom[1]=10'd370; assign rom[2]=10'd290; assign rom[3]=10'd307; assign rom[4]=10'd546; assign rom[5]=10'd291; assign rom[6]=10'd561; assign rom[7]=10'd292; assign rom[8]=10'd293; assign rom[9]=10'd300; assign rom[10]=10'd294; assign rom[11]=10'd297; assign rom[12]=10'd295; assign rom[13]=10'd296; assign rom[14]=10'd0; assign rom[15]=10'd1; assign rom[16]=10'd2; assign rom[17]=10'd3; assign rom[18]=10'd298; assign rom[19]=10'd299; assign rom[20]=10'd4; assign rom[21]=10'd5; assign rom[22]=10'd6; assign rom[23]=10'd7; assign rom[24]=10'd301; assign rom[25]=10'd304; assign rom[26]=10'd302; assign rom[27]=10'd303; assign rom[28]=10'd8; assign rom[29]=10'd9; assign rom[30]=10'd10; assign rom[31]=10'd11; assign rom[32]=10'd305; assign rom[33]=10'd306; assign rom[34]=10'd12; assign rom[35]=10'd13; assign rom[36]=10'd14; assign rom[37]=10'd15; assign rom[38]=10'd308; assign rom[39]=10'd339; assign rom[40]=10'd309; assign rom[41]=10'd324; assign rom[42]=10'd310; assign rom[43]=10'd317; assign rom[44]=10'd311; assign rom[45]=10'd314; assign rom[46]=10'd312; assign rom[47]=10'd313; assign rom[48]=10'd16; assign rom[49]=10'd17; assign rom[50]=10'd18; assign rom[51]=10'd19; assign rom[52]=10'd315; assign rom[53]=10'd316; assign rom[54]=10'd20; assign rom[55]=10'd21; assign rom[56]=10'd22; assign rom[57]=10'd23; assign rom[58]=10'd318; assign rom[59]=10'd321; assign rom[60]=10'd319; assign rom[61]=10'd320; assign rom[62]=10'd24; assign rom[63]=10'd25; assign rom[64]=10'd26; assign rom[65]=10'd27; assign rom[66]=10'd322; assign rom[67]=10'd323; assign rom[68]=10'd28; assign rom[69]=10'd29; assign rom[70]=10'd30; assign rom[71]=10'd31; assign rom[72]=10'd325; assign rom[73]=10'd332; assign rom[74]=10'd326; assign rom[75]=10'd329; assign rom[76]=10'd327; assign rom[77]=10'd328; assign rom[78]=10'd32; assign rom[79]=10'd33; assign rom[80]=10'd34; assign rom[81]=10'd35; assign rom[82]=10'd330; assign rom[83]=10'd331; assign rom[84]=10'd36; assign rom[85]=10'd37; assign rom[86]=10'd38; assign rom[87]=10'd39; assign rom[88]=10'd333; assign rom[89]=10'd336; assign rom[90]=10'd334; assign rom[91]=10'd335; assign rom[92]=10'd40; assign rom[93]=10'd41; assign rom[94]=10'd42; assign rom[95]=10'd43; assign rom[96]=10'd337; assign rom[97]=10'd338; assign rom[98]=10'd44; assign rom[99]=10'd45; assign rom[100]=10'd46; assign rom[101]=10'd47; assign rom[102]=10'd340; assign rom[103]=10'd355; assign rom[104]=10'd341; assign rom[105]=10'd348; assign rom[106]=10'd342; assign rom[107]=10'd345; assign rom[108]=10'd343; assign rom[109]=10'd344; assign rom[110]=10'd48; assign rom[111]=10'd49; assign rom[112]=10'd50; assign rom[113]=10'd51; assign rom[114]=10'd346; assign rom[115]=10'd347; assign rom[116]=10'd52; assign rom[117]=10'd53; assign rom[118]=10'd54; assign rom[119]=10'd55; assign rom[120]=10'd349; assign rom[121]=10'd352; assign rom[122]=10'd350; assign rom[123]=10'd351; assign rom[124]=10'd56; assign rom[125]=10'd57; assign rom[126]=10'd58; assign rom[127]=10'd59; assign rom[128]=10'd353; assign rom[129]=10'd354; assign rom[130]=10'd60; assign rom[131]=10'd61; assign rom[132]=10'd62; assign rom[133]=10'd63; assign rom[134]=10'd356; assign rom[135]=10'd363; assign rom[136]=10'd357; assign rom[137]=10'd360; assign rom[138]=10'd358; assign rom[139]=10'd359; assign rom[140]=10'd64; assign rom[141]=10'd65; assign rom[142]=10'd66; assign rom[143]=10'd67; assign rom[144]=10'd361; assign rom[145]=10'd362; assign rom[146]=10'd68; assign rom[147]=10'd69; assign rom[148]=10'd70; assign rom[149]=10'd71; assign rom[150]=10'd364; assign rom[151]=10'd367; assign rom[152]=10'd365; assign rom[153]=10'd366; assign rom[154]=10'd72; assign rom[155]=10'd73; assign rom[156]=10'd74; assign rom[157]=10'd75; assign rom[158]=10'd368; assign rom[159]=10'd369; assign rom[160]=10'd76; assign rom[161]=10'd77; assign rom[162]=10'd78; assign rom[163]=10'd79; assign rom[164]=10'd371; assign rom[165]=10'd434; assign rom[166]=10'd372; assign rom[167]=10'd403; assign rom[168]=10'd373; assign rom[169]=10'd388; assign rom[170]=10'd37
|
||
|
|
||
|
always @ (posedge clk)
|
||
|
rddata <= rom[rdaddr];
|
||
|
|
||
|
endmodule
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
module fixed_distree (
|
||
|
input logic clk,
|
||
|
input logic [5:0] rdaddr,
|
||
|
output logic [9:0] rddata
|
||
|
);
|
||
|
|
||
|
wire [9:0] rom [64]; assign rom[0]=10'd33; assign rom[1]=10'd48; assign rom[2]=10'd34; assign rom[3]=10'd41; assign rom[4]=10'd35; assign rom[5]=10'd38; assign rom[6]=10'd36; assign rom[7]=10'd37; assign rom[8]=10'd0; assign rom[9]=10'd1; assign rom[10]=10'd2; assign rom[11]=10'd3; assign rom[12]=10'd39; assign rom[13]=10'd40; assign rom[14]=10'd4; assign rom[15]=10'd5; assign rom[16]=10'd6; assign rom[17]=10'd7; assign rom[18]=10'd42; assign rom[19]=10'd45; assign rom[20]=10'd43; assign rom[21]=10'd44; assign rom[22]=10'd8; assign rom[23]=10'd9; assign rom[24]=10'd10; assign rom[25]=10'd11; assign rom[26]=10'd46; assign rom[27]=10'd47; assign rom[28]=10'd12; assign rom[29]=10'd13; assign rom[30]=10'd14; assign rom[31]=10'd15; assign rom[32]=10'd49; assign rom[33]=10'd56; assign rom[34]=10'd50; assign rom[35]=10'd53; assign rom[36]=10'd51; assign rom[37]=10'd52; assign rom[38]=10'd16; assign rom[39]=10'd17; assign rom[40]=10'd18; assign rom[41]=10'd19; assign rom[42]=10'd54; assign rom[43]=10'd55; assign rom[44]=10'd20; assign rom[45]=10'd21; assign rom[46]=10'd22; assign rom[47]=10'd23; assign rom[48]=10'd57; assign rom[49]=10'd60; assign rom[50]=10'd58; assign rom[51]=10'd59; assign rom[52]=10'd24; assign rom[53]=10'd25; assign rom[54]=10'd26; assign rom[55]=10'd27; assign rom[56]=10'd61; assign rom[57]=10'd62; assign rom[58]=10'd28; assign rom[59]=10'd29; assign rom[60]=10'd30; assign rom[61]=10'd31; assign rom[62]=10'd0; assign rom[63]=10'd0;
|
||
|
|
||
|
always @ (posedge clk)
|
||
|
rddata <= rom[rdaddr];
|
||
|
|
||
|
endmodule
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
module huffman_build #(
|
||
|
parameter NUMCODES = 288,
|
||
|
parameter CODEBITS = 5,
|
||
|
parameter BITLENGTH= 15,
|
||
|
parameter OUTWIDTH = 10
|
||
|
) (
|
||
|
clk,
|
||
|
wren, wraddr, wrdata,
|
||
|
run , done,
|
||
|
rdaddr, rddata
|
||
|
);
|
||
|
|
||
|
function automatic integer clogb2(input integer val);
|
||
|
integer valtmp;
|
||
|
valtmp = val;
|
||
|
for(clogb2=0; valtmp>0; clogb2=clogb2+1) valtmp = valtmp>>1;
|
||
|
endfunction
|
||
|
|
||
|
input clk;
|
||
|
input wren;
|
||
|
input [ clogb2(NUMCODES-1)-1:0] wraddr;
|
||
|
input [ CODEBITS -1:0] wrdata;
|
||
|
input run;
|
||
|
output done;
|
||
|
input [clogb2(2*NUMCODES-1)-1:0] rdaddr;
|
||
|
output [ OUTWIDTH-1:0] rddata;
|
||
|
|
||
|
wire clk;
|
||
|
wire wren;
|
||
|
wire [ clogb2(NUMCODES-1)-1:0] wraddr;
|
||
|
wire [ CODEBITS -1:0] wrdata;
|
||
|
wire run;
|
||
|
wire done;
|
||
|
wire [clogb2(2*NUMCODES-1)-1:0] rdaddr;
|
||
|
wire [ OUTWIDTH-1:0] rddata;
|
||
|
|
||
|
reg [clogb2(NUMCODES)-1:0] blcount [BITLENGTH];
|
||
|
reg [ 31:0] nextcode [BITLENGTH+1];
|
||
|
|
||
|
reg clear_tree2d = 1'b0;
|
||
|
reg build_tree2d = 1'b0;
|
||
|
reg [clogb2(BITLENGTH)-1:0] idx = '0;
|
||
|
reg [clogb2(2*NUMCODES+1)-1:0] clearidx = '0;
|
||
|
reg [ clogb2(NUMCODES)-1:0] nn='0, nnn, lnn='0;
|
||
|
reg [CODEBITS-1:0] ii='0, lii='0;
|
||
|
reg [CODEBITS-1:0] blenn, blen = '0;
|
||
|
wire [31:0] tree1d = nextcode[blen];
|
||
|
wire islast = (blen==0 || ii==0);
|
||
|
reg [clogb2(2*NUMCODES-1)-1:0] nodefilled = '0;
|
||
|
reg [clogb2(2*NUMCODES-1)-1:0] ntreepos, treepos='0;
|
||
|
wire [clogb2(2*NUMCODES-1) :0] ntpos= {ntreepos, tree1d[ii]};
|
||
|
reg [clogb2(2*NUMCODES-1) :0] tpos = '0;
|
||
|
wire rdfilled;
|
||
|
reg valid = 1'b0;
|
||
|
wire [OUTWIDTH-1:0] wrtree2d = (lii==0) ? lnn : nodefilled + (clogb2(2*NUMCODES-1))'(NUMCODES);
|
||
|
reg alldone = 1'b0;
|
||
|
|
||
|
assign done = alldone & run;
|
||
|
|
||
|
initial for(int i=0; i< BITLENGTH; i++) blcount[i] = '0;
|
||
|
initial for(int i=0; i<=BITLENGTH; i++) nextcode[i] = '0;
|
||
|
|
||
|
always @ (posedge clk) begin
|
||
|
valid <= build_tree2d & nn<NUMCODES & blen>0;
|
||
|
treepos <= ntreepos;
|
||
|
tpos <= ntpos;
|
||
|
lii <= ii;
|
||
|
lnn <= nn;
|
||
|
end
|
||
|
|
||
|
always @ (posedge clk)
|
||
|
if(islast)
|
||
|
blen <= blenn;
|
||
|
|
||
|
always @ (posedge clk)
|
||
|
if(done) begin
|
||
|
for(int i=0; i<BITLENGTH; i++)
|
||
|
blcount[i] <= '0;
|
||
|
end else begin
|
||
|
if(wren && wrdata<BITLENGTH)
|
||
|
blcount[wrdata] <= blcount[wrdata] + (clogb2(NUMCODES))'(1);
|
||
|
end
|
||
|
|
||
|
always_comb
|
||
|
if(build_tree2d)
|
||
|
nnn <= (nn<NUMCODES && islast) ? nn + (clogb2(NUMCODES))'(1) : nn;
|
||
|
else
|
||
|
nnn <= (idx<BITLENGTH) ? '1 : '0;
|
||
|
|
||
|
always @ (posedge clk)
|
||
|
nn <= nnn;
|
||
|
|
||
|
always @ (posedge clk) begin
|
||
|
nextcode[0] <= 0;
|
||
|
alldone <= 1'b0;
|
||
|
if(run) begin
|
||
|
if(~clear_tree2d) begin
|
||
|
if(clearidx<(2*NUMCODES)) begin
|
||
|
clearidx <= clearidx + (clogb2(2*NUMCODES+1))'(1);
|
||
|
end else begin
|
||
|
clear_tree2d <= 1'b1;
|
||
|
end
|
||
|
end else if(build_tree2d) begin
|
||
|
if(nn<NUMCODES) begin
|
||
|
if(islast) begin
|
||
|
ii <= blenn - (CODEBITS)'(1);
|
||
|
if(blen>0)
|
||
|
nextcode[blen] <= tree1d + 1;
|
||
|
end else
|
||
|
ii <= ii - (CODEBITS)'(1);
|
||
|
end else
|
||
|
alldone <= 1'b1;
|
||
|
end else begin
|
||
|
if(idx<BITLENGTH) begin
|
||
|
idx <= idx + (clogb2(BITLENGTH))'(1);
|
||
|
nextcode[idx+1] <= ( (nextcode[idx] + blcount[idx]) << 1 );
|
||
|
end else begin
|
||
|
ii <= blen - (CODEBITS)'(1);
|
||
|
build_tree2d <= 1'b1;
|
||
|
end
|
||
|
end
|
||
|
end else begin
|
||
|
ii <= '0;
|
||
|
idx <= '0;
|
||
|
build_tree2d <= 1'b0;
|
||
|
clearidx <= '0;
|
||
|
clear_tree2d <= 1'b0;
|
||
|
end
|
||
|
end
|
||
|
|
||
|
always_comb
|
||
|
if(~run)
|
||
|
ntreepos <= 0;
|
||
|
else if(valid) begin
|
||
|
if(~rdfilled)
|
||
|
ntreepos <= (clogb2(2*NUMCODES-1))'(rddata) - (clogb2(2*NUMCODES-1))'(NUMCODES);
|
||
|
else
|
||
|
ntreepos <= (lii==0) ? '0 : nodefilled;
|
||
|
end else
|
||
|
ntreepos <= treepos;
|
||
|
|
||
|
always @ (posedge clk)
|
||
|
if(~run)
|
||
|
nodefilled <= 1;
|
||
|
else if(valid & rdfilled & lii>0)
|
||
|
nodefilled <= nodefilled + (clogb2(2*NUMCODES-1))'(1);
|
||
|
|
||
|
RamSinglePort #(
|
||
|
.SIZE ( NUMCODES ),
|
||
|
.WIDTH ( CODEBITS )
|
||
|
) ram_for_bitlens (
|
||
|
.clk ( clk ),
|
||
|
.wen ( wren ),
|
||
|
.waddr ( wraddr ),
|
||
|
.wdata ( wrdata ),
|
||
|
.raddr ( (clogb2(NUMCODES-1))'(nnn) + (clogb2(NUMCODES-1))'(1) ),
|
||
|
.rdata ( blenn )
|
||
|
);
|
||
|
|
||
|
RamSinglePort #(
|
||
|
.SIZE ( NUMCODES * 2 ),
|
||
|
.WIDTH ( OUTWIDTH + 1 )
|
||
|
) ram_for_tree2d (
|
||
|
.clk ( clk ),
|
||
|
.wen ( clearidx<(2*NUMCODES) | (valid & rdfilled) ),
|
||
|
.waddr ( (clogb2(2*NUMCODES-1))'(clearidx<(2*NUMCODES) ? clearidx : tpos ) ),
|
||
|
.wdata ( clearidx<(2*NUMCODES) ? {1'b1,{OUTWIDTH{1'b0}}} : {1'b0, wrtree2d} ),
|
||
|
.raddr ( (clogb2(2*NUMCODES-1))'(alldone ? rdaddr : ntpos ) ),
|
||
|
.rdata ( {rdfilled, rddata} )
|
||
|
);
|
||
|
|
||
|
endmodule
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
module repeat_buffer #(
|
||
|
parameter DWIDTH = 8
|
||
|
) (
|
||
|
input clk,
|
||
|
|
||
|
input ivalid,
|
||
|
input [DWIDTH-1:0] idata,
|
||
|
|
||
|
input repeat_en,
|
||
|
input repeat_start,
|
||
|
input [ 15:0] repeat_dist,
|
||
|
|
||
|
output ovalid,
|
||
|
output [DWIDTH-1:0] odata
|
||
|
);
|
||
|
|
||
|
wire [15:0] MAXLEN = 16'd33792;
|
||
|
|
||
|
reg [15:0] wptr = '0;
|
||
|
reg [15:0] rptr = '0;
|
||
|
reg [15:0] sptr = '0;
|
||
|
reg [15:0] eptr = '0;
|
||
|
wire [15:0] sptrw = (wptr<repeat_dist) ? wptr + MAXLEN - repeat_dist : wptr - repeat_dist;
|
||
|
wire [15:0] eptrw = (wptr<16'd1) ? wptr + MAXLEN - 16'd1 : wptr - 16'd1;
|
||
|
|
||
|
reg repeat_valid = 1'b0;
|
||
|
wire [DWIDTH-1:0] repeat_data;
|
||
|
|
||
|
assign ovalid = ivalid | repeat_valid;
|
||
|
assign odata = repeat_valid ? repeat_data : idata;
|
||
|
|
||
|
always @ (posedge clk)
|
||
|
if(ovalid)
|
||
|
wptr <= (wptr<(MAXLEN-16'd1)) ? wptr+16'd1 : '0;
|
||
|
|
||
|
always @ (posedge clk) begin
|
||
|
if(repeat_start) begin
|
||
|
rptr <= sptrw;
|
||
|
sptr <= sptrw;
|
||
|
eptr <= eptrw;
|
||
|
end else if(repeat_en) begin
|
||
|
if(rptr!=eptr)
|
||
|
rptr <= (rptr<(MAXLEN-16'd1)) ? rptr+16'd1 : '0;
|
||
|
else
|
||
|
rptr <= sptr;
|
||
|
end
|
||
|
end
|
||
|
|
||
|
always @ (posedge clk)
|
||
|
repeat_valid <= repeat_en;
|
||
|
|
||
|
RamSinglePort #(
|
||
|
.SIZE ( 33792 ),
|
||
|
.WIDTH ( DWIDTH )
|
||
|
) ram_for_bitlens (
|
||
|
.clk ( clk ),
|
||
|
.wen ( ovalid ),
|
||
|
.waddr ( wptr ),
|
||
|
.wdata ( odata ),
|
||
|
.raddr ( rptr ),
|
||
|
.rdata ( repeat_data )
|
||
|
);
|
||
|
|
||
|
endmodule
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
module unfilter(
|
||
|
input wire rst,
|
||
|
input wire clk,
|
||
|
// config parameter
|
||
|
input wire [ 1:0] bpp, // bytes per pixel (-1)
|
||
|
input wire [13:0] bpr, // bytes per row
|
||
|
// data input
|
||
|
input wire ivalid,
|
||
|
input wire [ 7:0] idata,
|
||
|
// data output
|
||
|
output reg ovalid,
|
||
|
output reg [ 7:0] odata
|
||
|
);
|
||
|
|
||
|
initial ovalid = 1'b0;
|
||
|
initial odata = '0;
|
||
|
|
||
|
function automatic logic [7:0] paeth(input [7:0] a, input [7:0] b, input [7:0] c);
|
||
|
automatic logic signed [10:0] sa = {3'h0, a};
|
||
|
automatic logic signed [10:0] sb = {3'h0, b};
|
||
|
automatic logic signed [10:0] sc = {3'h0, c};
|
||
|
automatic logic signed [10:0] p = sa + sb - sc;
|
||
|
automatic logic signed [10:0] pa = p > sa ? p - sa : sa - p;
|
||
|
automatic logic signed [10:0] pb = p > sb ? p - sb : sb - p;
|
||
|
automatic logic signed [10:0] pc = p > sc ? p - sc : sc - p;
|
||
|
if (pa <= pb && pa <= pc)
|
||
|
return a;
|
||
|
else if (pb <= pc)
|
||
|
return b;
|
||
|
else
|
||
|
return c;
|
||
|
endfunction
|
||
|
|
||
|
reg nfirstrow = 1'b0;
|
||
|
reg [13:0] col = '0;
|
||
|
reg [ 2:0] mode = '0;
|
||
|
reg [ 7:0] fdata;
|
||
|
wire [ 7:0] LLdata, UUdata, ULdata;
|
||
|
wire nfirstcol = col > (14'h1+bpp);
|
||
|
wire [ 8:0] SSdata = (nfirstcol ? {1'b0,LLdata} : 9'h0) + (nfirstrow ? {1'b0,UUdata} : 9'h0);
|
||
|
|
||
|
|
||
|
always @ (posedge clk or posedge rst)
|
||
|
if(rst) begin
|
||
|
nfirstrow <= 1'b0;
|
||
|
col <= '0;
|
||
|
end else begin
|
||
|
if(ivalid) begin
|
||
|
if(col<bpr) begin
|
||
|
col <= col + 14'h1;
|
||
|
end else begin
|
||
|
nfirstrow <= 1'b1;
|
||
|
col <= '0;
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
always @ (posedge clk or posedge rst)
|
||
|
if(rst)
|
||
|
mode <= '0;
|
||
|
else begin
|
||
|
if(ivalid && col==14'h0)
|
||
|
mode <= idata[2:0];
|
||
|
end
|
||
|
|
||
|
always_comb
|
||
|
case(mode)
|
||
|
3'd0 : fdata <= idata;
|
||
|
3'd1 : fdata <= idata + (nfirstcol ? LLdata : 8'h0);
|
||
|
3'd2 : fdata <= idata + (nfirstrow ? UUdata : 8'h0);
|
||
|
3'd3 : fdata <= idata + SSdata[8:1];
|
||
|
default: fdata <= idata + paeth(
|
||
|
(nfirstcol ? LLdata : 8'h0),
|
||
|
(nfirstrow ? UUdata : 8'h0),
|
||
|
(nfirstrow&nfirstcol ? ULdata : 8'h0)
|
||
|
);
|
||
|
endcase
|
||
|
|
||
|
always @ (posedge clk or posedge rst)
|
||
|
if(rst) begin
|
||
|
ovalid <= 1'b0;
|
||
|
odata <= '0;
|
||
|
end else begin
|
||
|
ovalid <= (ivalid && col!=14'h0);
|
||
|
if(ivalid && col!=14'h0)
|
||
|
odata <= fdata;
|
||
|
end
|
||
|
|
||
|
shift_regs #(
|
||
|
.MAXLEN_LEVEL ( 2 ),
|
||
|
.DWIDTH ( 8 )
|
||
|
) shift_i1 (
|
||
|
.rst ( rst ),
|
||
|
.clk ( clk ),
|
||
|
.length ( bpp ),
|
||
|
.ivalid ( ivalid ),
|
||
|
.idata ( fdata ),
|
||
|
.odata ( LLdata )
|
||
|
);
|
||
|
|
||
|
shift_buffer #(
|
||
|
.MAXLEN_LEVEL ( 14 ),
|
||
|
.DWIDTH ( 8 )
|
||
|
) shift_i2 (
|
||
|
.rst ( rst ),
|
||
|
.clk ( clk ),
|
||
|
.length ( bpr ),
|
||
|
.ivalid ( ivalid ),
|
||
|
.idata ( fdata ),
|
||
|
.odata ( UUdata )
|
||
|
);
|
||
|
|
||
|
shift_regs #(
|
||
|
.MAXLEN_LEVEL ( 2 ),
|
||
|
.DWIDTH ( 8 )
|
||
|
) shift_i3 (
|
||
|
.rst ( rst ),
|
||
|
.clk ( clk ),
|
||
|
.length ( bpp ),
|
||
|
.ivalid ( ivalid ),
|
||
|
.idata ( UUdata ),
|
||
|
.odata ( ULdata )
|
||
|
);
|
||
|
|
||
|
endmodule
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
module shift_buffer #(
|
||
|
parameter MAXLEN_LEVEL = 14,
|
||
|
parameter DWIDTH = 8
|
||
|
) (
|
||
|
input rst,
|
||
|
input clk,
|
||
|
|
||
|
input [MAXLEN_LEVEL-1:0] length, // length = 1 ~ (1<<MAXLEN_LEVEL)
|
||
|
|
||
|
input ivalid,
|
||
|
input [ DWIDTH-1:0] idata,
|
||
|
|
||
|
output [ DWIDTH-1:0] odata
|
||
|
);
|
||
|
|
||
|
localparam MAXLEN = 1<<MAXLEN_LEVEL;
|
||
|
|
||
|
reg rvalid = 1'b0;
|
||
|
wire [ DWIDTH-1:0] rdata;
|
||
|
reg [ DWIDTH-1:0] ldata = '0;
|
||
|
reg [ DWIDTH-1:0] lidata= '0;
|
||
|
reg [MAXLEN_LEVEL-1:0] ptr = '0;
|
||
|
|
||
|
always @ (posedge clk or posedge rst)
|
||
|
if(rst)
|
||
|
lidata <= '0;
|
||
|
else begin
|
||
|
if(ivalid)
|
||
|
lidata <= idata;
|
||
|
end
|
||
|
|
||
|
always @ (posedge clk or posedge rst)
|
||
|
if(rst)
|
||
|
ptr <= '0;
|
||
|
else begin
|
||
|
if(ivalid) begin
|
||
|
if(ptr<(length-1))
|
||
|
ptr <= ptr + (MAXLEN_LEVEL)'(1);
|
||
|
else
|
||
|
ptr <= '0;
|
||
|
end
|
||
|
end
|
||
|
|
||
|
always @ (posedge clk or posedge rst)
|
||
|
if(rst) begin
|
||
|
ldata <= '0;
|
||
|
rvalid <= 1'b0;
|
||
|
end else begin
|
||
|
if(rvalid)
|
||
|
ldata <= rdata;
|
||
|
rvalid <= ivalid;
|
||
|
end
|
||
|
|
||
|
assign odata = (length=='0) ? lidata : (rvalid ? rdata : ldata);
|
||
|
|
||
|
RamSinglePort #(
|
||
|
.SIZE ( MAXLEN ),
|
||
|
.WIDTH ( DWIDTH )
|
||
|
) ram_for_bitlens (
|
||
|
.clk ( clk ),
|
||
|
.wen ( ivalid ),
|
||
|
.waddr ( ptr ),
|
||
|
.wdata ( idata ),
|
||
|
.raddr ( ptr ),
|
||
|
.rdata ( rdata )
|
||
|
);
|
||
|
|
||
|
endmodule
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
module shift_regs #(
|
||
|
parameter MAXLEN_LEVEL = 2,
|
||
|
parameter DWIDTH = 8
|
||
|
) (
|
||
|
input rst,
|
||
|
input clk,
|
||
|
|
||
|
input [MAXLEN_LEVEL-1:0] length, // length = 1~(1<<MAXLEN_LEVEL)
|
||
|
|
||
|
input ivalid,
|
||
|
input [ DWIDTH-1:0] idata,
|
||
|
|
||
|
output [ DWIDTH-1:0] odata
|
||
|
);
|
||
|
|
||
|
localparam MAXLEN = 1<<MAXLEN_LEVEL;
|
||
|
|
||
|
reg [DWIDTH-1:0] shift_data [MAXLEN] = '{MAXLEN{'0}};
|
||
|
|
||
|
assign odata = shift_data [length];
|
||
|
|
||
|
generate
|
||
|
genvar ii;
|
||
|
for(ii=0; ii<MAXLEN; ii++) begin : generate_shift_registers
|
||
|
if(ii==0) begin
|
||
|
always @ (posedge clk or posedge rst)
|
||
|
if(rst) begin
|
||
|
shift_data[ii] <= '0;
|
||
|
end else begin
|
||
|
if(ivalid)
|
||
|
shift_data[ii] <= idata;
|
||
|
end
|
||
|
end else begin
|
||
|
always @ (posedge clk or posedge rst)
|
||
|
if(rst) begin
|
||
|
shift_data[ii] <= '0;
|
||
|
end else begin
|
||
|
if(ivalid)
|
||
|
shift_data[ii] <= shift_data[ii-1];
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
endgenerate
|
||
|
|
||
|
endmodule
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
module RamSinglePort #(
|
||
|
parameter SIZE = 1024,
|
||
|
parameter WIDTH = 32
|
||
|
)(
|
||
|
clk,
|
||
|
wen,
|
||
|
waddr,
|
||
|
wdata,
|
||
|
raddr,
|
||
|
rdata
|
||
|
);
|
||
|
|
||
|
function automatic integer clogb2(input integer val);
|
||
|
integer valtmp;
|
||
|
valtmp = val;
|
||
|
for(clogb2=0; valtmp>0; clogb2=clogb2+1) valtmp = valtmp>>1;
|
||
|
endfunction
|
||
|
|
||
|
input clk;
|
||
|
input wen;
|
||
|
input [clogb2(SIZE-1)-1:0] waddr;
|
||
|
input [WIDTH-1:0] wdata;
|
||
|
input [clogb2(SIZE-1)-1:0] raddr;
|
||
|
output [WIDTH-1:0] rdata;
|
||
|
|
||
|
wire clk;
|
||
|
wire wen;
|
||
|
wire [clogb2(SIZE-1)-1:0] waddr;
|
||
|
wire [WIDTH-1:0] wdata;
|
||
|
wire [clogb2(SIZE-1)-1:0] raddr;
|
||
|
reg [WIDTH-1:0] rdata;
|
||
|
|
||
|
reg [WIDTH-1:0] mem [SIZE];
|
||
|
|
||
|
always @ (posedge clk)
|
||
|
if(wen)
|
||
|
mem[waddr] <= wdata;
|
||
|
|
||
|
initial rdata = '0;
|
||
|
always @ (posedge clk)
|
||
|
rdata <= mem[raddr];
|
||
|
|
||
|
endmodule
|