Hard-PNG/RTL/hard_png.sv

1216 lines
87 KiB
Systemverilog
Raw Normal View History

2022-03-29 19:41:01 +08:00
//--------------------------------------------------------------------------------------------------------
// Module : hard_png
// Type : synthesizable, IP's top
// Standard: SystemVerilog 2005 (IEEE1800-2005)
// Function: png image decoder
//--------------------------------------------------------------------------------------------------------
module hard_png (
input wire rstn,
input wire clk,
// png data input stream
input wire ivalid,
output reg iready,
input wire [ 7:0] ibyte,
// image frame configuration output
output reg newframe,
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 [31:0] height, // image height
// pixel output
output reg ovalid,
output wire [ 7:0] opixelr, opixelg, opixelb, opixela
);
initial newframe = 1'b0;
initial ovalid = 1'b0;
reg imagevalid = '0;
reg isplte = '0;
reg [ 1:0] bpp = '0; // bytes per pixel
reg [13:0] ppr = '0; // pixel per row
reg [13:0] bpr = '0; // bytes per row
reg [31:0] rpf = '0; // rows per frame
assign colortype = isplte ? 3'd4 : {1'b0,bpp};
assign width = ppr;
assign height = rpf;
reg pvalid;
reg pready;
reg [ 7:0] pbyte;
reg mvalid = '0;
reg [ 7:0] mbyte = '0;
reg bvalid = '0;
reg [ 7:0] bbyte = '0;
reg plte_wen = '0;
reg [ 7:0] plte_waddr = '0;
reg [23:0] plte_wdata = '0;
reg [23:0] plte_rdata;
//-----------------------------------------------------------------------------------------------------------------------
// png parser
//-----------------------------------------------------------------------------------------------------------------------
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=ii+1) begin : generate_latchbytes_connect
assign lastbytes[ii] = latchbytes[ii];
always @ (posedge clk or negedge rstn)
if(~rstn)
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 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;
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(imagevalid && cnt>0 && curr_name==IDAT && gapcnt==2'd0) begin
iready = pready;
pvalid = ivalid;
pbyte = ibyte;
end else begin
iready = 1'b1;
pvalid = 1'b0;
pbyte = '0;
end
always @ (posedge clk or negedge rstn)
if(~rstn) 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;
newframe <= 1'b0;
plte_wen <= 1'b0;
plte_waddr <= '0;
plte_wdata <= '0;
plte_bytecnt <= '0;
plte_pixcnt <= '0;
end else begin
newframe <= 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
newframe <= 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(pready)
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
//-----------------------------------------------------------------------------------------------------------------------
// uz_inflate
//-----------------------------------------------------------------------------------------------------------------------
reg end_stream = '0;
wire huffman_ovalid;
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 [ 7:0] rbyte = '0;
reg tvalid;
wire tready;
reg tbit;
always @ (posedge clk or negedge rstn)
if(~rstn) begin
mvalid <= 1'b0;
mbyte <= '0;
end else begin
if(~imagevalid) begin
mvalid <= 1'b0;
mbyte <= '0;
end else if(raw_mode) begin
mvalid <= raw_ovalid;
mbyte <= raw_obyte;
end else begin
mvalid <= huffman_ovalid;
mbyte <= huffman_obyte;
end
end
always_comb
if(~imagevalid) begin
raw_ovalid = 1'b0;
raw_obyte = '0;
pready = 1'b0;
tvalid = 1'b0;
tbit = 1'b0;
end else begin
raw_ovalid = 1'b0;
raw_obyte = '0;
if(raw_mode) begin
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
always @ (posedge clk or negedge rstn)
if(~rstn) begin
raw_mode <= 1'b0;
uz_cnt <= '0;
rbyte <= '0;
rcnt <= '0;
status <= '0;
end else begin
if(~imagevalid) begin
raw_mode <= 1'b0;
uz_cnt <= '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
rcnt <= '0;
status <= '0;
if(raw_format) begin
if(pvalid) begin
raw_mode <= 1'b1;
rcnt[ 7:0] <= pbyte;
end
uz_cnt <= '0;
rbyte <= '0;
end else begin
if(uz_cnt==3'h0) begin
if(pvalid & tready) begin
uz_cnt <= uz_cnt + 3'h1;
rbyte <= pbyte;
end
end else begin
if(tready)
uz_cnt <= uz_cnt + 3'h1;
end
end
end
end
//--------------------------------------------------------------------------------------------------------------------
// huffman inflate
//--------------------------------------------------------------------------------------------------------------------
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_new = 1'b1;
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} 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 codetree_ien = ~end_stream & ~raw_format & 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);
assign tready = end_stream | (~raw_format & (
( 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) ) |
( tree_done & ~codetree_codeen & ~distree_codeen & (huffman_status==T || huffman_status==D || (huffman_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;
reg [ 9:0] codetree_rdata_fixed;
wire [ 5:0] distree_raddr;
wire [ 9:0] distree_rdata;
reg [ 9:0] 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;
{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;
huffman_status <= T;
symbol_valid <= 1'b0;
symbol <= '0;
irepeat <= 1'b0;
srepeat <= 1'b0;
len_last <= '0;
endtask
always @ (posedge clk or negedge rstn)
if(~rstn) begin
{raw_format, end_stream} <= '0;
decoder_new <= 1'b1;
reset_all_regs;
end else begin
if(raw_mode) begin
{raw_format, end_stream} <= '0;
decoder_new <= 1'b1;
reset_all_regs;
end else begin
symbol_valid <= 1'b0;
symbol <= '0;
irepeat <= 1'b0;
srepeat <= 1'b0;
decoder_new <= 1'b0;
lentree_write();
codetree_write();
distree_write();
if(precode_wpt<=2) begin
lentree_run <= 1'b0;
tree_run <= 1'b0;
if(tvalid) begin
precode_wpt <= precode_wpt + 5'd1;
if(precode_wpt==0) begin
bfin <= tbit;
end else if(precode_wpt==1) begin
bfix <= tbit;
end else begin
case({tbit,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(tvalid) begin
precode_reg <= {tbit, 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(tvalid) begin
if(ibcnt<2'd2) begin
iword[ibcnt[0]] <= tbit;
ibcnt <= ibcnt + 2'd1;
end else begin
lentree_write(1'b1, CLCL[lentree_wpt], {tbit, 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(tvalid) begin
repeat_code_pt <= repeat_code_pt - 3'd1;
repeat_code[3'd7-repeat_code_pt] <= tbit;
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(tvalid) begin
dscnt <= dscnt - 4'd1;
distancee[dsmax-dscnt] <= tbit;
end
end else if(tcnt>3'd0) begin
if(tvalid) begin
tcnt <= tcnt - 3'd1;
lengthe[tmax-tcnt] <= tbit;
end
end else if(huffman_status==R) begin
huffman_status <= S;
len_last <= length;
srepeat <= 1'b1;
end else if(huffman_status==S) begin
if(len_last>0) begin
irepeat <= 1'b1;
len_last <= len_last - 9'd1;
end else
huffman_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];
huffman_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];
huffman_status <= R;
end
end
end
end
//--------------------------------------------------------------------------------------------------------------------
// lentree huffman builder
//--------------------------------------------------------------------------------------------------------------------
huffman_builder #(
.NUMCODES ( 19 ),
.CODEBITS ( 3 ),
.BITLENGTH ( 7 ),
.OUTWIDTH ( 6 )
) lentree_builder (
.rstn ( rstn ),
.clk ( clk ),
.wren ( lentree_wen ),
.wraddr ( lentree_waddr ),
.wrdata ( lentree_wdata ),
.run ( lentree_run ),
.done ( lentree_done ),
.rdaddr ( lentree_raddr ),
.rddata ( lentree_rdata )
);
//--------------------------------------------------------------------------------------------------------------------
// lentree huffman decoder
//--------------------------------------------------------------------------------------------------------------------
huffman_decoder #(
.NUMCODES ( 19 ),
.OUTWIDTH ( 6 )
) lentree_decoder (
.rstn ( rstn ),
.clk ( clk ),
.inew ( decoder_new ),
.ien ( lentree_ien ),
.ibit ( tbit ),
.oen ( lentree_codeen ),
.ocode ( lentree_code ),
.rdaddr ( lentree_raddr ),
.rddata ( lentree_rdata )
);
//--------------------------------------------------------------------------------------------------------------------
// codetree huffman builder
//--------------------------------------------------------------------------------------------------------------------
huffman_builder #(
.NUMCODES ( 288 ),
.CODEBITS ( 5 ),
.BITLENGTH ( 15 ),
.OUTWIDTH ( 10 )
) codetree_builder (
.rstn ( rstn ),
.clk ( clk ),
.wren ( codetree_wen ),
.wraddr ( codetree_waddr ),
.wrdata ( (5)'(codetree_wdata) ),
.run ( tree_run ),
.done ( codetree_done ),
.rdaddr ( codetree_raddr ),
.rddata ( codetree_rdata )
);
//--------------------------------------------------------------------------------------------------------------------
// codetree_fixed
//--------------------------------------------------------------------------------------------------------------------
wire [9:0] rom_fixed_codetree [1024];
assign rom_fixed_codetree[0]=10'd289; assign rom_fixed_codetree[1]=10'd370; assign rom_fixed_codetree[2]=10'd290; assign rom_fixed_codetree[3]=10'd307; assign rom_fixed_codetree[4]=10'd546; assign rom_fixed_codetree[5]=10'd291; assign rom_fixed_codetree[6]=10'd561; assign rom_fixed_codetree[7]=10'd292; assign rom_fixed_codetree[8]=10'd293; assign rom_fixed_codetree[9]=10'd300; assign rom_fixed_codetree[10]=10'd294; assign rom_fixed_codetree[11]=10'd297; assign rom_fixed_codetree[12]=10'd295; assign rom_fixed_codetree[13]=10'd296; assign rom_fixed_codetree[14]=10'd0; assign rom_fixed_codetree[15]=10'd1; assign rom_fixed_codetree[16]=10'd2; assign rom_fixed_codetree[17]=10'd3; assign rom_fixed_codetree[18]=10'd298; assign rom_fixed_codetree[19]=10'd299; assign rom_fixed_codetree[20]=10'd4; assign rom_fixed_codetree[21]=10'd5; assign rom_fixed_codetree[22]=10'd6; assign rom_fixed_codetree[23]=10'd7; assign rom_fixed_codetree[24]=10'd301; assign rom_fixed_codetree[25]=10'd304; assign rom_fixed_codetree[26]=10'd302; assign rom_fixed_codetree[27]=10'd303; assign rom_fixed_codetree[28]=10'd8; assign rom_fixed_codetree[29]=10'd9; assign rom_fixed_codetree[30]=10'd10; assign rom_fixed_codetree[31]=10'd11; assign rom_fixed_codetree[32]=10'd305; assign rom_fixed_codetree[33]=10'd306; assign rom_fixed_codetree[34]=10'd12; assign rom_fixed_codetree[35]=10'd13; assign rom_fixed_codetree[36]=10'd14; assign rom_fixed_codetree[37]=10'd15; assign rom_fixed_codetree[38]=10'd308; assign rom_fixed_codetree[39]=10'd339; assign rom_fixed_codetree[40]=10'd309; assign rom_fixed_codetree[41]=10'd324; assign rom_fixed_codetree[42]=10'd310; assign rom_fixed_codetree[43]=10'd317; assign rom_fixed_codetree[44]=10'd311; assign rom_fixed_codetree[45]=10'd314; assign rom_fixed_codetree[46]=10'd312; assign rom_fixed_codetree[47]=10'd313; assign rom_fixed_codetree[48]=10'd16; assign rom_fixed_codetree[49]=10'd17; assign rom_fixed_codetree[50]=10'd18; assign rom_fixed_codetree[51]=10'd19; assign rom_fixed_codetree[52]=10'd315; assign rom_fixed_codetree[53]=10'd316; assign rom_fixed_codetree[54]=10'd20; assign rom_fixed_codetree[55]=10'd21; assign rom_fixed_codetree[56]=10'd22; assign rom_fixed_codetree[57]=10'd23; assign rom_fixed_codetree[58]=10'd318; assign rom_fixed_codetree[59]=10'd321; assign rom_fixed_codetree[60]=10'd319; assign rom_fixed_codetree[61]=10'd320; assign rom_fixed_codetree[62]=10'd24; assign rom_fixed_codetree[63]=10'd25; assign rom_fixed_codetree[64]=10'd26; assign rom_fixed_codetree[65]=10'd27; assign rom_fixed_codetree[66]=10'd322; assign rom_fixed_codetree[67]=10'd323; assign rom_fixed_codetree[68]=10'd28; assign rom_fixed_codetree[69]=10'd29; assign rom_fixed_codetree[70]=10'd30; assign rom_fixed_codetree[71]=10'd31; assign rom_fixed_codetree[72]=10'd325; assign rom_fixed_codetree[73]=10'd332; assign rom_fixed_codetree[74]=10'd326; assign rom_fixed_codetree[75]=10'd329; assign rom_fixed_codetree[76]=10'd327; assign rom_fixed_codetree[77]=10'd328; assign rom_fixed_codetree[78]=10'd32; assign rom_fixed_codetree[79]=10'd33; assign rom_fixed_codetree[80]=10'd34; assign rom_fixed_codetree[81]=10'd35; assign rom_fixed_codetree[82]=10'd330; assign rom_fixed_codetree[83]=10'd331; assign rom_fixed_codetree[84]=10'd36; assign rom_fixed_codetree[85]=10'd37; assign rom_fixed_codetree[86]=10'd38; assign rom_fixed_codetree[87]=10'd39; assign rom_fixed_codetree[88]=10'd333; assign rom_fixed_codetree[89]=10'd336; assign rom_fixed_codetree[90]=10'd334; assign rom_fixed_codetree[91]=10'd335; assign rom_fixed_codetree[92]=10'd40; assign rom_fixed_codetree[93]=10'd41; assign rom_fixed_codetree[94]=10'd42; assign rom_fixed_codetree[95]=10'd43; assign rom_fixed_codetree[96]=10'd337; assign rom_fixed_codetree[97]=10'd338; assign rom_fixed_codetree[98]=10'd44; assign rom_fixed_codetree[99]=10'd45; assign rom_fixed_codetree[100]=10'd46; assign rom_fixed_codetree[101]=10'd47; assign rom_fixed_codetree[102]=10'd340; assign rom_fixed_codetree[103]=10'd355; assign rom_fixed_codetree[104]=10'd341; assign rom_fixed_codetree[105]=10'd348; assign rom_fixed_codetr
always @ (posedge clk) codetree_rdata_fixed <= rom_fixed_codetree[codetree_raddr];
//--------------------------------------------------------------------------------------------------------------------
// codetree huffman decoder
//--------------------------------------------------------------------------------------------------------------------
huffman_decoder #(
.NUMCODES ( 288 ),
.OUTWIDTH ( 10 )
) codetree_decoder (
.rstn ( rstn ),
.clk ( clk ),
.inew ( decoder_new ),
.ien ( codetree_ien ),
.ibit ( tbit ),
.oen ( codetree_codeen),
.ocode ( codetree_code ),
.rdaddr ( codetree_raddr ),
.rddata ( fixed_tree ? codetree_rdata_fixed : codetree_rdata )
);
//--------------------------------------------------------------------------------------------------------------------
// distree huffman builder
//--------------------------------------------------------------------------------------------------------------------
huffman_builder #(
.NUMCODES ( 32 ),
.CODEBITS ( 5 ),
.BITLENGTH ( 15 ),
.OUTWIDTH ( 10 )
) distree_builder (
.rstn ( rstn ),
.clk ( clk ),
.wren ( distree_wen ),
.wraddr ( distree_waddr ),
.wrdata ( (5)'(distree_wdata) ),
.run ( tree_run ),
.done ( distree_done ),
.rdaddr ( distree_raddr ),
.rddata ( distree_rdata )
);
//--------------------------------------------------------------------------------------------------------------------
// distree_fixed
//--------------------------------------------------------------------------------------------------------------------
wire [9:0] rom_fixed_distree [64];
assign rom_fixed_distree[0]=10'd33; assign rom_fixed_distree[1]=10'd48; assign rom_fixed_distree[2]=10'd34; assign rom_fixed_distree[3]=10'd41; assign rom_fixed_distree[4]=10'd35; assign rom_fixed_distree[5]=10'd38; assign rom_fixed_distree[6]=10'd36; assign rom_fixed_distree[7]=10'd37; assign rom_fixed_distree[8]=10'd0; assign rom_fixed_distree[9]=10'd1; assign rom_fixed_distree[10]=10'd2; assign rom_fixed_distree[11]=10'd3; assign rom_fixed_distree[12]=10'd39; assign rom_fixed_distree[13]=10'd40; assign rom_fixed_distree[14]=10'd4; assign rom_fixed_distree[15]=10'd5; assign rom_fixed_distree[16]=10'd6; assign rom_fixed_distree[17]=10'd7; assign rom_fixed_distree[18]=10'd42; assign rom_fixed_distree[19]=10'd45; assign rom_fixed_distree[20]=10'd43; assign rom_fixed_distree[21]=10'd44; assign rom_fixed_distree[22]=10'd8; assign rom_fixed_distree[23]=10'd9; assign rom_fixed_distree[24]=10'd10; assign rom_fixed_distree[25]=10'd11; assign rom_fixed_distree[26]=10'd46; assign rom_fixed_distree[27]=10'd47; assign rom_fixed_distree[28]=10'd12; assign rom_fixed_distree[29]=10'd13; assign rom_fixed_distree[30]=10'd14; assign rom_fixed_distree[31]=10'd15; assign rom_fixed_distree[32]=10'd49; assign rom_fixed_distree[33]=10'd56; assign rom_fixed_distree[34]=10'd50; assign rom_fixed_distree[35]=10'd53; assign rom_fixed_distree[36]=10'd51; assign rom_fixed_distree[37]=10'd52; assign rom_fixed_distree[38]=10'd16; assign rom_fixed_distree[39]=10'd17; assign rom_fixed_distree[40]=10'd18; assign rom_fixed_distree[41]=10'd19; assign rom_fixed_distree[42]=10'd54; assign rom_fixed_distree[43]=10'd55; assign rom_fixed_distree[44]=10'd20; assign rom_fixed_distree[45]=10'd21; assign rom_fixed_distree[46]=10'd22; assign rom_fixed_distree[47]=10'd23; assign rom_fixed_distree[48]=10'd57; assign rom_fixed_distree[49]=10'd60; assign rom_fixed_distree[50]=10'd58; assign rom_fixed_distree[51]=10'd59; assign rom_fixed_distree[52]=10'd24; assign rom_fixed_distree[53]=10'd25; assign rom_fixed_distree[54]=10'd26; assign rom_fixed_distree[55]=10'd27; assign rom_fixed_distree[56]=10'd61; assign rom_fixed_distree[57]=10'd62; assign rom_fixed_distree[58]=10'd28; assign rom_fixed_distree[59]=10'd29; assign rom_fixed_distree[60]=10'd30; assign rom_fixed_distree[61]=10'd31; assign rom_fixed_distree[62]=10'd0; assign rom_fixed_distree[63]=10'd0;
always @ (posedge clk) distree_rdata_fixed <= rom_fixed_distree[distree_raddr];
//--------------------------------------------------------------------------------------------------------------------
// distree huffman decoder
//--------------------------------------------------------------------------------------------------------------------
huffman_decoder #(
.NUMCODES ( 32 ),
.OUTWIDTH ( 10 )
) distree_decoder (
.rstn ( rstn ),
.clk ( clk ),
.inew ( decoder_new ),
.ien ( distree_ien ),
.ibit ( tbit ),
.oen ( distree_codeen ),
.ocode ( distree_code ),
.rdaddr ( distree_raddr ),
.rddata ( fixed_tree ? distree_rdata_fixed : distree_rdata )
);
//--------------------------------------------------------------------------------------------------------------------
// repeat buffer
//--------------------------------------------------------------------------------------------------------------------
parameter [15:0] REPEAT_BUFFER_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<distance) ? wptr + REPEAT_BUFFER_MAXLEN - distance : wptr - distance;
wire [15:0] eptrw = (wptr<16'd1) ? wptr + REPEAT_BUFFER_MAXLEN - 16'd1 : wptr - 16'd1;
reg repeat_valid = 1'b0;
reg [7:0] repeat_data;
assign huffman_ovalid = symbol_valid | repeat_valid;
assign huffman_obyte = repeat_valid ? repeat_data : symbol;
always @ (posedge clk or negedge rstn)
if(~rstn)
wptr <= '0;
else begin
if(huffman_ovalid) wptr <= (wptr<(REPEAT_BUFFER_MAXLEN-16'd1)) ? wptr+16'd1 : '0;
end
always @ (posedge clk or negedge rstn)
if(~rstn) begin
rptr <= '0;
sptr <= '0;
eptr <= '0;
end else begin
if(srepeat) begin
rptr <= sptrw;
sptr <= sptrw;
eptr <= eptrw;
end else if(irepeat) begin
if(rptr!=eptr)
rptr <= (rptr<(REPEAT_BUFFER_MAXLEN-16'd1)) ? rptr+16'd1 : '0;
else
rptr <= sptr;
end
end
always @ (posedge clk or negedge rstn)
if(~rstn)
repeat_valid <= '0;
else
repeat_valid <= irepeat;
reg [7:0] mem_repeat_buffer [REPEAT_BUFFER_MAXLEN];
always @ (posedge clk)
if(huffman_ovalid) mem_repeat_buffer[wptr] <= huffman_obyte;
always @ (posedge clk)
repeat_data <= mem_repeat_buffer[rptr];
//-----------------------------------------------------------------------------------------------------------------------
// unfilter
//-----------------------------------------------------------------------------------------------------------------------
function automatic logic [7:0] paeth(input [7:0] a, input [7:0] b, input [7:0] c);
logic signed [10:0] sa, sb, sc, p, pa, pb, pc;
sa = {3'h0, a};
sb = {3'h0, b};
sc = {3'h0, c};
p = sa + sb - sc;
pa = p > sa ? p - sa : sa - p;
pb = p > sb ? p - sb : sb - p;
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 negedge rstn)
if(~rstn) begin
nfirstrow <= 1'b0;
col <= '0;
end else begin
if(~imagevalid) begin
nfirstrow <= 1'b0;
col <= '0;
end else if(mvalid) begin
if(col<bpr) begin
col <= col + 14'h1;
end else begin
nfirstrow <= 1'b1;
col <= '0;
end
end
end
always @ (posedge clk or negedge rstn)
if(~rstn) begin
mode <= '0;
end else begin
if(~imagevalid) begin
mode <= '0;
end else if(mvalid && col==14'h0)
mode <= mbyte[2:0];
end
always_comb
case(mode)
3'd0 : fdata = mbyte;
3'd1 : fdata = mbyte + (nfirstcol ? LLdata : 8'h0);
3'd2 : fdata = mbyte + (nfirstrow ? UUdata : 8'h0);
3'd3 : fdata = mbyte + SSdata[8:1];
default: fdata = mbyte + paeth( (nfirstcol ? LLdata : 8'h0),
(nfirstrow ? UUdata : 8'h0),
(nfirstrow&nfirstcol ? ULdata : 8'h0) );
endcase
always @ (posedge clk or negedge rstn)
if(~rstn) begin
bvalid <= 1'b0;
bbyte <= '0;
end else begin
if(~imagevalid) begin
bvalid <= 1'b0;
bbyte <= '0;
end else begin
bvalid <= (mvalid && col!=14'h0);
if(mvalid && col!=14'h0) bbyte <= fdata;
end
end
// shift reg for current line
reg [7:0] mem_sr_currline [4];
initial for(int i=0; i<4; i=i+1) mem_sr_currline[i] = '0;
assign LLdata = mem_sr_currline [bpp];
always @ (posedge clk or negedge rstn)
if(~rstn) begin
mem_sr_currline[0] <= '0;
end else begin
if(~imagevalid) begin
mem_sr_currline[0] <= '0;
end else if(mvalid)
mem_sr_currline[0] <= fdata;
end
generate genvar isrcl;
for(isrcl=0; isrcl<3; isrcl=isrcl+1) begin : gen_sr_currline
always @ (posedge clk or negedge rstn)
if(~rstn) begin
mem_sr_currline[isrcl+1] <= '0;
end else begin
if(~imagevalid) begin
mem_sr_currline[isrcl+1] <= '0;
end else if(mvalid)
mem_sr_currline[isrcl+1] <= mem_sr_currline[isrcl];
end
end
endgenerate
// shift reg for previous line
reg [7:0] mem_sr_prevline [4];
initial for(int i=0; i<4; i=i+1) mem_sr_prevline[i] = '0;
assign ULdata = mem_sr_prevline [bpp];
always @ (posedge clk or negedge rstn)
if(~rstn) begin
mem_sr_prevline[0] <= '0;
end else begin
if(~imagevalid) begin
mem_sr_prevline[0] <= '0;
end else if(mvalid)
mem_sr_prevline[0] <= UUdata;
end
generate genvar isrpl;
for(isrpl=0; isrpl<3; isrpl=isrpl+1) begin : gen_sr_prevline
always @ (posedge clk or negedge rstn)
if(~rstn) begin
mem_sr_prevline[isrpl+1] <= '0;
end else begin
if(~imagevalid) begin
mem_sr_prevline[isrpl+1] <= '0;
end else if(mvalid)
mem_sr_prevline[isrpl+1] <= mem_sr_prevline[isrpl];
end
end
endgenerate
// shift buffer from current line to previous line
reg sb_rvalid = 1'b0;
reg [ 7:0] sb_rdata;
reg [ 7:0] sb_ldata = '0;
reg [ 7:0] sb_lidata = '0;
reg [13:0] sb_ptr = '0;
always @ (posedge clk or negedge rstn)
if(~rstn) begin
sb_lidata <= '0;
end else begin
if(~imagevalid) begin
sb_lidata <= '0;
end else if(mvalid)
sb_lidata <= fdata;
end
always @ (posedge clk or negedge rstn)
if(~rstn) begin
sb_ptr <= '0;
end else begin
if(~imagevalid) begin
sb_ptr <= '0;
end else if(mvalid) begin
if(sb_ptr < (bpr-14'd1))
sb_ptr <= sb_ptr + 14'd1;
else
sb_ptr <= '0;
end
end
always @ (posedge clk or negedge rstn)
if(~rstn) begin
sb_ldata <= '0;
sb_rvalid <= 1'b0;
end else begin
if(~imagevalid) begin
sb_ldata <= '0;
sb_rvalid <= 1'b0;
end else begin
if(sb_rvalid)
sb_ldata <= sb_rdata;
sb_rvalid <= mvalid;
end
end
reg [7:0] mem_sb [1<<14];
always @ (posedge clk)
if(mvalid)
mem_sb[sb_ptr] <= fdata;
always @ (posedge clk)
sb_rdata <= mem_sb[sb_ptr];
assign UUdata = (bpr == '0) ? sb_lidata : (sb_rvalid ? sb_rdata : sb_ldata);
//-------------------------------------------------------------------------------------------------------------
// build pixel
//-------------------------------------------------------------------------------------------------------------
reg [1:0] pixcnt = '0;
reg [7:0] pr='0, pg='0, pb='0, pa='0;
assign opixelr = isplte ? plte_rdata[23:16] : pr;
assign opixelg = isplte ? plte_rdata[15: 8] : pg;
assign opixelb = isplte ? plte_rdata[ 7: 0] : pb;
assign opixela = isplte ? 8'hff : pa;
always @ (posedge clk or negedge rstn)
if(~rstn) begin
pixcnt <= '0;
ovalid <= 1'b0;
{pr, pg, pb, pa} <= 0;
end else begin
ovalid <= 1'b0;
if(newframe) begin
pixcnt <= '0;
{pr, pg, pb, pa} <= 0;
end else if(bvalid) begin
case(pixcnt)
2'd0 : {pr, pg, pb, pa} <= {bbyte, bbyte, bbyte, 8'hff};
2'd1 : { pa} <= { bbyte};
2'd2 : { pg, pb, pa} <= { pa, bbyte, 8'hff};
2'd3 : { pa} <= { bbyte};
endcase
if(pixcnt<bpp) begin
pixcnt <= pixcnt + 2'd1;
ovalid <= 1'b0;
end else begin
pixcnt <= 2'd0;
ovalid <= 1'b1;
end
end
end
//-------------------------------------------------------------------------------------------------------------
// PLTE mem
//-------------------------------------------------------------------------------------------------------------
reg [23:0] mem_plte [256];
always @ (posedge clk)
if(plte_wen)
mem_plte[plte_waddr] <= plte_wdata;
always @ (posedge clk)
plte_rdata <= mem_plte[bbyte];
endmodule