📄 color_proc333.v
字号:
.din(di[7:0]),
.strt(ccv_start), //****************
.y(y_in[7:0]),
.q(c_in0[7:0]),
.yaddr({yaddrw[7],yaddrw[5:3],yaddrw[6],yaddrw[2:0]}), //
.ywe(ywe),
.caddr(caddrw[6:0]),
.cwe(cwe),
.pre_first_out(cs_pre_first_out),
.bayer_phase(bayer_phase[1:0]),
.n000(n000[7:0]),
.n255(n255[7:0]));
RAMB4_S8_S8 i_y_buff(//.DOA(),
.DOB(y_out[7:0]),
.ADDRA({wpage,yaddrw[7:0]}),
.CLKA(clk),
.DIA(y_in[7:0]),
.ENA(1'b1),.RSTA(1'b0),
.WEA(ywe),
.ADDRB({rpage,raddr[7:0]}),
.CLKB(clk),
.DIB(8'b0),.ENB(!raddr[8]),.RSTB(1'b0),.WEB(1'b0));
RAMB4_S8_S8 i_CrCb_buff(//.DOA(),
.DOB(c_out[7:0]),
.ADDRA({wpage,1'b0,caddrw[6:0]}),
.CLKA(clk),
.DIA(c_in[7:0]),
.ENA(1'b1),.RSTA(1'b0),
.WEA(cwe),
.ADDRB({rpage,1'b0,raddr[6:0]}),
.CLKB(clk),
.DIB(8'b0),.ENB(raddr[8]),.RSTB(1'b0),.WEB(1'b0));
endmodule
/*
09/07/2002 Andrey Filippov
Compared to spreadsheet simulation. Y - matches, CbCr in ~25% give result one less than spreadsheet simulation.
It is always odd and s.s. gives next even
TODO: optimize sequencing counters and possibly add some extra bits - as to calculate int((a+b+c+d)/4)
instead of int((int((a+b)/2)+int((c+d)/2))/2)
Color space converter processes one MCU at a time. It receives 16x16 8-bit bayer pixels (now it is always in (GR/BG)
sequence). With some latency it will produce 16x16x8 bit Y data (could be some artifacts on the borders) in scan-line
sequence and clock rate and Cb and Cr at the same time at half rate, so 4:2:0 will be generated at the same
time.
update: now it processes overlapping tiles (18x18) to avoid problems on the MCU boarders
Y= 0.299*R+0.587*G+0.114*B
Cb=-0.168*R-0.3313*G+0.5*B = 0.564*(B-Y)+128
Cr=0.5*R-0.4187*G-0.0813*B = 0.713*(R-Y)+128
For Bayer array (GR/BG)(bayer_phase[1:0]==0), and pixels P[Y,X]:
R[0,0]=0.5* (P[0,-1]+P[0,1])
R[0,1]= P[0,1]
R[1,0]=0.25*(P[0,-1]+P[0,1]+P[2,-1]+P[2,1])
R[1,1]=0.5 *(P[0,1] +P[2,1])
G[0,0]= P[0,0]
G[0,1]=0.25*(P[-1,1]+P[0,0]+P[0,2]+P[1,1])
G[1,0]=0.25*(P[0,0]+P[1,-1]+P[1,1]+P[2,0])
G[1,1]= P[1,1]
B[0,0]=0.5* (P[-1,0]+P[1,0])
B[0,1]=0.25*(P[-1,0]+P[-1,2]+P[1,0]+P[1,2])
B[1,0]= P[1,0]
B[1,1]=0.5* (P[1,0]+P[1,2])
Y[0,0]=0.299*0.5*(P[0,-1]+P[0,1]) + 0.587*P[0,0] + 0.114*0.5* (P[-1,0]+P[1,0])
Y[0,1]=0.299*P[0,1]+0.587*0.25*(P[-1,1]+P[0,0]+P[0,2]+P[1,1])+0.114*0.25*(P[-1,0]+P[-1,2]+P[1,0]+P[1,2])
Y[1,0]=0.299*0.25*(P[0,-1]+P[0,1]+P[2,-1]+P[2,1])+0.587*0.25*(P[0,0]+P[1,-1]+P[1,1]+P[2,0])+0.114*P[1,0]
Y[1,1]=0.299*0.5 *(P[0,1] +P[2,1])+0.587*P[1,1]+0.114*0.5* (P[1,0]+P[1,2])
Y[0,0]=(0x96*P[0,0]+ 0x4d*((P[0,-1]+P[0,1])/2) + 0x1d*((P[-1,0]+P[1,0])/2))>>8
Y[0,1]=(0x4d*P[0,1]+ 0x96*((P[-1,1]+P[0,0]+P[0,2]+P[1,1])/4)+ 0x1d*((P[-1,0]+P[-1,2]+P[1,0]+P[1,2])/4))>>8
Y[1,0]=(0x1d*P[1,0]+ 0x96*((P[0,0]+P[1,-1]+P[1,1]+P[2,0])/4)+ 0x4d*((P[0,-1]+P[0,1]+P[2,-1]+P[2,1])/4))>>8
Y[1,1]=(0x96*P[1,1]+ 0x1d*((P[1,0]+P[1,2])/2) + 0x4d*((P[0,1] +P[2,1])/2)))>>8
Cb and Cy are needed 1 for each 4 pixels (4:2:0)
(YC= 0.299*P[0,1]+0.587*(0.5*P[0,0]+P[1,1])+0.114*P[1,0] )
Cb=0.564*(P[1,0]-(0.299*P[0,1]+0.587*0.5*(P[0,0]+P[1,1])+0.114*P[1,0]))+128
Cr=0.713*(P[0,1]-(0.299*P[0,1]+0.587*0.5*(P[0,0]+P[1,1])+0.114*P[1,0]))+128
Cb=0.564*(P[1,0]-(0.299*P[0,1]+0.587*0.5*(P[0,0]+P[1,1])+0.114*P[1,0]))+128=
0.564*P[1,0]-0.299*0.564*P[0,1]-0.587*0.564*0.5*(P[0,0]+P[1,1])-0.114*0.564*P[1,0]))+128=
0.564*P[1,0]-0.168636*P[0,1]-0.165534*P[0,0]-0.165534*P[1,1]-0.064638*P[1,0]+128=
0.499362*P[1,0]-0.168636*P[0,1]-0.165534*P[0,0]-0.165534*P[1,1]+128=
-0.165534*P[0,0] -0.168636*P[0,1] +0.499362*P[1,0] -0.165534*P[1,1]+ 128=
(-256*0.165534*P[0,0] -256*0.168636*P[0,1] +256*0.499362*P[1,0] -256*0.165534*P[1,1])>>8+ 128=
(-42.5*P[0,0] -43*P[0,1] +128*P[1,0] -42.5*P[1,1])>>8+ 128=
(-85*((P[0,0]+P[1,1])/2) -43*P[0,1] +128*P[1,0])>>8+ 128=
(-0x55*((P[0,0]+P[1,1])/2) -2b*P[0,1] +P[1,0]<<7)>>8+ 0x80=
(-0x55*((P[0,0]+P[1,1])/2) -2b*P[0,1])>>8 +P[1,0]>>1 +0x80=
Cr=0.713*(P[0,1]-(0.299*P[0,1]+0.587*0.5*(P[0,0]+P[1,1])+0.114*P[1,0]))+128=
0.713* P[0,1]- 0.713*0.299*P[0,1] - 0.713*0.587*0.5*P[0,0]- 0.713*0.587*0.5*P[1,1] -0.713*0.114*P[1,0]+128=
0.713* P[0,1]- 0.213187*P[0,1] - 0.2092655*P[0,0]- 0.2092655*P[1,1] -0.081282*P[1,0]+128=
0.499813* P[0,1] -0.2092655*P[0,0] -0.2092655*P[1,1] -0.081282*P[1,0]+128=
-0.2092655*P[0,0] +0.499813* P[0,1] -0.081282*P[1,0] -0.2092655*P[1,1] +128=
(-256*0.2092655*P[0,0] +256*0.499813* P[0,1] -256*0.081282*P[1,0] -256*0.2092655*P[1,1])>>8 +128=
(-54*P[0,0] +128* P[0,1] -21*P[1,0] -54*P[1,1])>>8 +128= // rounded up, sum=129 -> decreasing
(-53.5*P[0,0] +128* P[0,1] -21*P[1,0] -53.5*P[1,1])>>8 +128=
(-107*((P[0,0]+P[1,1])/2) +P[0,1]<<7 -21*P[1,0])>>8 +128=
(-0x6b*((P[0,0]+P[1,1])/2) +P[0,1]<<7 -0x15*P[1,0])>>8 +0x80=
(-0x6b*((P[0,0]+P[1,1])/2) -0x15*P[1,0])>>8 +P[0,1]>>1 +0x80=
*/ /*
For Bayer array (RG/GB)(bayer_phase[1:0]==1), and pixels P[Y,X]:
R[0,0]= P[0,0]
R[0,1]=0.5 *(P[0,0]+P[0,2])
R[1,0]=0.5 *(P[0,0]+P[2,0])
R[1,1]=0.25*(P[0,0]+P[0,2]+P[2,0]+P[2,2])
G[0,0]=0.25*(P[-1,0]+P[0,-1]+P[0,1]+P[1,0])
G[0,1]= P[0,1]
G[1,0]= P[1,0]
G[1,1]=0.25*(P[0,1]+P[1,0]+P[1,2]+P[2,1])
B[0,0]=0.25*(P[-1,-1]+P[-1,1]+P[1,-1]+P[1,1])
B[0,1]=0.5* (P[-1,1]+P[1,1])
B[1,0]=0.5* (P[1,-1]+P[1,1])
B[1,1]= P[1,1]
Y[0,0]=0.299*P[0,0] + 0.587*0.25*(P[-1,0]+P[0,-1]+P[0,1]+P[1,0]) + 0.114*0.25*(P[-1,-1]+P[-1,1]+P[1,-1]+P[1,1])
Y[0,1]=0.299*0.5 *(P[0,0]+P[0,2])+0.587*P[0,1]+0.114*0.5* (P[-1,1]+P[1,1])
Y[1,0]=0.299*0.5 *(P[0,0]+P[2,0])+0.587*P[1,0]+0.114*0.5* (P[1,-1]+P[1,1])
Y[1,1]=0.299*0.25*(P[0,0]+P[0,2]+P[2,0]+P[2,2])+0.587*0.25*(P[0,1]+P[1,0]+P[1,2]+P[2,1])+0.114*P[1,1]
Y[0,0]=(0x4d*P[0,0]+ 0x96*((P[-1,0]+P[0,-1]+P[0,1]+P[1,0])/4) + 0x1d*((P[-1,-1]+P[-1,1]+P[1,-1]+P[1,1])/4))>>8
Y[0,1]=(0x96*P[0,1]+ 0x4d*((P[0,0]+P[0,2])/2)+ 0x1d*((P[-1,1]+P[1,1])/2))>>8
Y[1,0]=(0x96*P[1,0]+ 0x4d*((P[0,0]+P[2,0])/2)+ 0x1d*((P[1,-1]+P[1,1])/2))>>8
Y[1,1]=(0x1d*P[1,1]+ 0x96*((P[0,1]+P[1,0]+P[1,2]+P[2,1])/4) + 0x4d*((P[0,0]+P[0,2]+P[2,0]+P[2,2])/4)))>>8
Cb and Cy are needed 1 for each 4 pixels (4:2:0)
(YC= 0.299*P[0,0]+0.587*(0.5*P[0,1]+P[1,0])+0.114*P[1,1] )
Cb=0.564*(P[1,1]-(0.299*P[0,0]+0.587*0.5*(P[0,1]+P[1,0])+0.114*P[1,1]))+128
Cr=0.713*(P[0,0]-(0.299*P[0,0]+0.587*0.5*(P[0,1]+P[1,0])+0.114*P[1,1]))+128
Cb=0.564*(P[1,1]-(0.299*P[0,0]+0.587*0.5*(P[0,1]+P[1,0])+0.114*P[1,1]))+128=
(-0x55*((P[0,1]+P[1,0])/2) -2b*P[0,0] +P[1,1]<<7)>>8+ 0x80=
(-0x55*((P[0,1]+P[1,0])/2) -2b*P[0,0])>>8 +P[1,1]>>1 +0x80=
Cr=0.713*(P[0,0]-(0.299*P[0,0]+0.587*0.5*(P[0,1]+P[1,0])+0.114*P[1,1]))+128=
(-0x6b*((P[0,1]+P[1,0])/2) +P[0,0]<<7 -0x15*P[1,1])>>8 +0x80=
(-0x6b*((P[0,1]+P[1,0])/2) -0x15*P[1,1])>>8 +P[0,0]>>1 +0x80=
----
*/ /*
For Bayer array (BG/GR)(bayer_phase[1:0]==2), and pixels P[Y,X]:
R[0,0]=0.25*(P[-1,-1]+P[-1,1]+P[1,-1]+P[1,1])
R[0,1]=0.5 *(P[-1,1] +P[1,1])
R[1,0]=0.5* (P[1,-1]+P[1,1])
R[1,1]= P[1,1]
G[0,0]=0.25*(P[-1,0]+P[0,-1]+P[0,1]+P[1,0])
G[0,1]= P[0,1]
G[1,0]= P[1,0]
G[1,1]=0.25*(P[0,1]+P[1,0]+P[1,2]+P[2,1])
B[0,0]= P[0,0]
B[0,1]=0.5* (P[0,0]+P[0,2])
B[1,0]=0.5* (P[0,0]+P[2,0])
B[1,1]=0.25*(P[0,0]+P[0,2]+P[2,0]+P[2,2])
Y[0,0]=0.299*0.25*(P[-1,-1]+P[-1,1]+P[1,-1]+P[1,1]) + 0.587*0.25*(P[-1,0]+P[0,-1]+P[0,1]+P[1,0]) + 0.114* P[0,0]
Y[0,1]=0.299*0.5 *(P[-1,1] +P[1,1])+0.587*P[0,1]+0.114*0.5* (P[0,0]+P[0,2])
Y[1,0]=0.299*0.5* (P[1,-1]+P[1,1])+0.587*P[1,0]+0.114*0.5* (P[0,0]+P[2,0])
Y[1,1]=0.299*P[1,1]+0.587*0.25*(P[0,1]+P[1,0]+P[1,2]+P[2,1])+0.114*0.25*(P[0,0]+P[0,2]+P[2,0]+P[2,2])
Y[0,0]=(0x1d*P[0,0]+ 0x96*((P[-1,0]+P[0,-1]+P[0,1]+P[1,0])/4)+ 0x4d*((P[-1,-1]+P[-1,1]+P[1,-1]+P[1,1])/4))>>8
Y[0,1]=(0x96*P[0,1]+ 0x4d*((P[-1,1] +P[1,1])/2)+ 0x1d*((P[0,0]+P[0,2])/2))>>8
Y[1,0]=(0x96*P[1,0]+ 0x4d*((P[1,-1]+P[1,1])/2)+ 0x1d*((P[0,0]+P[2,0])/2))>>8
Y[1,1]=(0x4d*P[1,1]+ 0x96*((P[0,1]+P[1,0]+P[1,2]+P[2,1])/4) + 0x1d*((P[0,0]+P[0,2]+P[2,0]+P[2,2])/4)))>>8
Cb and Cy are needed 1 for each 4 pixels (4:2:0)
(YC= 0.299*P[1,1]+0.587*(0.5*P[1,0]+P[0,1])+0.114*P[0,0] )
Cb=0.564*(P[0,0]-(0.299*P[1,1]+0.587*0.5*(P[1,0]+P[0,1])+0.114*P[0,0]))+128
Cr=0.713*(P[1,1]-(0.299*P[1,1]+0.587*0.5*(P[1,0]+P[0,1])+0.114*P[0,0]))+128
Cb=0.564*(P[0,0]-(0.299*P[1,1]+0.587*0.5*(P[1,0]+P[0,1])+0.114*P[0,0]))+128=
(-0x55*((P[1,0]+P[0,1])/2) -2b*P[1,1] +P[0,0]<<7)>>8+ 0x80=
(-0x55*((P[1,0]+P[0,1])/2) -2b*P[1,1])>>8 +P[0,0]>>1 +0x80=
Cr=0.713*(P[1,1]-(0.299*P[1,1]+0.587*0.5*(P[1,0]+P[0,1])+0.114*P[0,0]))+128=
(-0x6b*((P[1,0]+P[0,1])/2) +P[1,1]<<7 -0x15*P[0,0])>>8 +0x80=
(-0x6b*((P[1,0]+P[0,1])/2) -0x15*P[0,0])>>8 +P[1,1]>>1 +0x80=
----
*/ /*
For Bayer array (GB/RG)(bayer_phase[1:0]==3), and pixels P[Y,X]:
R[0,0]=0.5 *(P[-1,0]+P[1,0])
R[0,1]=0.25*(P[-1,0]+P[-1,2]+P[1,0]+P[1,2])
R[1,0]= P[1,0]
R[1,1]=0.5 *(P[1,0]+P[1,2])
G[0,0]= P[0,0]
G[0,1]=0.25*(P[-1,1]+P[0,0]+P[0,2]+P[1,1])
G[1,0]=0.25*(P[0,0]+P[1,-1]+P[1,1]+P[2,0])
G[1,1]= P[1,1]
B[0,0]=0.5* (P[0,-1]+P[0,1])
B[0,1]= P[0,1]
B[1,0]=0.25*(P[0,-1]+P[0,1]+P[2,-1]+P[2,1])
B[1,1]=0.5* (P[0,1]+P[2,1])
Y[0,0]=0.299*0.5 *(P[-1,0]+P[1,0]) + 0.587*P[0,0] + 0.114*0.5* (P[0,-1]+P[0,1])
Y[0,1]=0.299*0.25*(P[-1,0]+P[-1,2]+P[1,0]+P[1,2])+0.587*0.25*(P[-1,1]+P[0,0]+P[0,2]+P[1,1])+0.114*P[0,1]
Y[1,0]=0.299*P[1,0]+0.587*0.25*(P[0,-1]+P[0,1]+P[2,-1]+P[2,1])+0.114*0.25*(P[0,-1]+P[0,1]+P[2,-1]+P[2,1])
Y[1,1]=0.299*0.5 *(P[1,0]+P[1,2])+0.587*P[1,1]+0.114*0.5* (P[0,1]+P[2,1])
Y[0,0]=(0x96*P[0,0]+ 0x4d*((P[-1,0]+P[1,0])/2) + 0x1d*((P[0,-1]+P[0,1])/2))>>8
Y[0,1]=(0x1d*P[0,1]+ 0x96*((P[-1,1]+P[0,0]+P[0,2]+P[1,1])/4)+ 0x4d*((P[-1,0]+P[-1,2]+P[1,0]+P[1,2])/4))>>8
Y[1,0]=(0x4d*P[1,0]+ 0x96*((P[0,0]+P[1,-1]+P[1,1]+P[2,0])/4)+ 0x1d*((P[0,-1]+P[0,1]+P[2,-1]+P[2,1])/4))>>8
Y[1,1]=(0x96*P[1,1]+ 0x4d*((P[1,0]+P[1,2])/2 + 0x1d*((P[0,1] +P[2,1])/2)))>>8
Cb and Cy are needed 1 for each 4 pixels (4:2:0)
(YC= 0.299*P[1,0]+0.587*(0.5*P[1,1]+P[0,0])+0.114*P[0,1] )
Cb=0.564*(P[0,1]-(0.299*P[1,0]+0.587*0.5*(P[1,1]+P[0,0])+0.114*P[0,1]))+128
Cr=0.713*(P[1,0]-(0.299*P[1,0]+0.587*0.5*(P[1,1]+P[0,0])+0.114*P[0,1]))+128
Cb=0.564*(P[0,1]-(0.299*P[1,0]+0.587*0.5*(P[1,1]+P[0,0])+0.114*P[0,1]))+128=
(-0x55*((P[1,1]+P[0,0])/2) -2b*P[1,0] +P[0,1]<<7)>>8+ 0x80=
(-0x55*((P[1,1]+P[0,0])/2) -2b*P[1,0])>>8 +P[0,1]>>1 +0x80=
Cr=0.713*(P[1,0]-(0.299*P[1,0]+0.587*0.5*(P[1,1]+P[0,0])+0.114*P[0,1]))+128=
(-0x6b*((P[1,1]+P[0,0])/2) +P[1,0]<<7 -0x15*P[0,1])>>8 +0x80=
(-0x6b*((P[1,1]+P[0,0])/2) -0x15*P[0,1])>>8 +P[1,0]>>1 +0x80=
----
*/
/* 02/24/2003 - modified to include bypass for monochrome mode*/
/* 06/29/2004 - added counting of pixels with value of 0 and 255 (limited to 255 to use just 8 bits) */
module csconvert(RST,CLK,mono,din,strt,y,q,yaddr,ywe,caddr,cwe,pre_first_out,bayer_phase, n000, n255);
input RST; // global reset
input CLK; // clock
input mono; // 1 - monochrome mode
input [7:0] din; // input bayer data in scanline sequence, GR/BG sequence
input strt; // marks the first input pixel - chaged to first in 3-rd row
output [7:0] y; // output Y (16x16) in scanline sequence. Valid if ys active
output [7:0] q; // output CbCr (8x8) each. Valid during cbs and crs
output [7:0] yaddr; // address for the external buffer memory to write 16x16x8bit Y data
output ywe; // wrire enable of Y data
output [6:0] caddr; // address for the external buffer memory 2x8x8x8bit Cb+Cr data (MSB=0 - Cb, 1 - Cr)
output cwe; // write enable for CbCr data
output pre_first_out;
input [1:0] bayer_phase;
output [7:0] n000;
output [7:0] n255;
// synthesis attribute shreg_extract of csconvert is yes;
wire [7:0] din;
wire ystrt,nxtline;
reg [7:0] yaddr; // address for the external buffer memory to write 16x16x8bit Y data
reg ywe; // wrire enable of Y data
reg [6:0] caddr; // address for the external buffer memory 2x8x8x8bit Cb+Cr data (MSB=0 - Cb, 1 - Cr)
reg cwe; // write enable for CbCr data
assign pre_first_out=ystrt;
reg odd_pix; // odd pixel (assumes even number of pixels in a line
reg odd_line; // odd line
reg pix_green;// (was "odd_pix==odd_line", now modified with bayer_phase[1:0]: bayer_phase[1]^bayer_phase[0]^(odd_pix==odd_line)
reg y_eq_0, y_eq_255;
reg [7:0] n000;
reg [7:0] n255;
SRL16 i_ystrt (.Q(ystrt), .D(strt), .CLK(CLK), .A0(1'b1), .A1(1'b0), .A2(1'b1), .A3(1'b0)); // dly=5+1
SRL16 i_nxtline(.Q(nxtline),.D(!RST && ywe && (yaddr[3:0]==4'hf) && (yaddr[7:4]!=4'hf)), .CLK(CLK), .A0(1'b1), .A1(1'b0), .A2(1'b0), .A3(1'b0)); // dly=1+1
always @ (posedge CLK) begin
ywe <= !RST && (ystrt || nxtline || (ywe && (yaddr[3:0]!=4'hf)));
yaddr[7:4] <= (RST || strt)? 4'h0: (nxtline?(yaddr[7:4]+1):yaddr[7:4]);
yaddr[3:0] <= ywe? (yaddr[3:0]+1):4'h0;
odd_pix <= RST || strt || ~odd_pix;
if (RST || strt) odd_line <= 1'b0;
else if (yaddr[3:0]==4'hd) odd_line <= ~odd_line;
if (RST || strt) pix_green <=bayer_phase[1]^bayer_phase[0];
else pix_green <=~(yaddr[3:0]==4'hd)^pix_green;
end
// First block generates 2 8-bit values (latency=3)- pixel (p2) and average value of previous and next pixel in the same
// row (pa). For the first pixel that "average" equals to next pixel, for the last - previous
reg [7:0] p0;
reg [7:0] p1;
reg [7:0] pd0;
reg [7:0] pa0;
wire [8:0] ppa;
always @ (posedge CLK) p0 <= din[7:0];
always @ (posedge CLK) p1 <= p0[7:0];
// always @ (posedge CLK) pd0 <= p1[7:0];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -