📄 color_proc333.v
字号:
/*
** -----------------------------------------------------------------------------**
** color_proc333.v
**
** Color space converter (bayer-> YCbCr 4:2:1) for JPEG compressor
**
** Copyright 2002-2004 Andrey Filippov
**
** -----------------------------------------------------------------------------**
** This file is part of X333
**
** X333 is free software (FPGA code); you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
**
** X333 is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with X333; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
** -----------------------------------------------------------------------------**
**
*/
// Modified to use 18x18 tiles on 09/14/2003
module color_proc (clk, // pixel clock (1/2 system clock - 60MHz?)
en, // Enable (0 will reset states)
en_sdc, // enable subtracting of DC component
go, // pulse to star/restart, level to ignore EOT
nblocks, // [15:0] number of 16x16 blocks to read (valid @ "go" pulse)
eot, // single-cycle end of transfer pulse
di, // [7:0]
sdram_a, // [10:0] (MSB - SDRAM buffer page number)
sdram_rdy, // SDRAM buffer ready
sdram_next, // request to read a page to SDRAM buffer
inc_sdrama, // enable read sdram buffer
dv_raw, // data valid for di (for testing to bypass color conversion - use di[7:0])
ignore_color, //zero Cb/Cr components
nomosaic, //no demosaic processing (needs ignore_color set)
do, // [8:0] data out (4:2:0) (signed, average=0)
avr, // [7:0] DC (average value)
dv, // out data valid (will go high for at least 64 cycles)
ds, // single-cycle mark of the first pixel in a 64 (8x8) - pixel block
tn, // [2:0] tile number 0..3 - Y, 4 - Cb, 5 - Cr (valid with start)
first, // sending first MCU (valid @ ds)
last, // sending last MCU (valid @ ds)
n000, // [7:0] number of zero pixels (255 if 256)
n255, // [7:0] number of 0xff pixels (255 if 256)
bayer_phase //[1:0]) bayer color filter phase 0:(GR/BG), 1:(RG/GB), 2: (BG/GR), 3: (GB/RG)
);
input ignore_color,nomosaic;
input clk, en, go, en_sdc;
input [15:0] nblocks;
output eot;
input [ 7:0] di;
output [ 10:0] sdram_a;
input sdram_rdy;
output sdram_next;
output inc_sdrama;
output dv_raw;
output [ 8:0] do;
output [ 7:0] avr;
output dv;
output ds;
output [ 2:0] tn;
output first;
output last;
output [7:0] n000;
output [7:0] n255;
input [1:0] bayer_phase;
wire [7:0] di;
wire [7:0] y_in; // data to buffer (Y component)
wire [7:0] c_in; // data to buffer (CbCr components)
wire [7:0] c_in0;
assign c_in[7:0]=ignore_color?8'h80:c_in0[7:0];
wire [7:0] y_out; // data from buffer
wire [7:0] c_out; // data from buffer
reg wpage; // page (0/1) where data is being written to (both Y and CbCr)
reg rpage; // page (0/1) from where data is sent out ( both Y and CbCr)
wire [7:0] yaddrw; // 2 MSB tile #, next 3 - row in a tile, last 3 - column in a tile
wire [6:0] caddrw; // color (MSB=0 - Cb, 1 - Cr)
wire ywe; // write enable to CbCr memory
wire cwe; // write enable to CbCr memory
reg [10:0] sdram_an;
reg [8:0] sdram_a_nomos;
reg [8:0] sdram_a_mos; // temporary to use lower 18x18 of 20x20 tiles
reg [4:0] line18;
wire [10:0] sdram_a;
reg tim2next;
reg tim2next1;
reg sdram_next;
reg this_rdy;
reg [15:0] bcntr; // down counter of blocks left
reg pend_next; //sdram_next is pending
reg eot;
reg go_d;
reg go_ds; // single_cycle
reg ccv_start; // start data to color converter from SDRAM (now delayed by 2 lines (active with the first pixel in 3-rd row)
reg ccv_start_en; //
reg ccv_out_start; // start output of YCbCr from buffers
reg [8:0] raddr; // output address of buffer memories (MSB selects Y(0)/CbCr(1))
wire dv,ds;
reg dv0; // "dv0" - one cycle ahead of "dv" to compensate for "do" register latency
reg ds0; // "ds0" - one cycle ahead of "ds" to compensate for "do" register latency
reg [8:0] do;
reg [8:0] pre_do;
wire [2:0] tn;
reg dv_raw;
wire inc_sdrama;
wire cs_pre_first_out;
// reg newAcc;
reg [13:0] accYA,accYB,accCb, accCr;
reg avm_we;
reg [2:0] avm_a;
wire [7:0] avm_d;
wire [7:0] avm_q;
reg [2:0] avm_s;
reg buf_sel;
reg willbe_first;
reg first,first0;
reg last,last0;
// assign sdram_a={sdram_an[9],(nomosaic?sdram_a_nomos[8:0]:sdram_an[8:0])};
assign sdram_a={sdram_an[10:9],(nomosaic?sdram_a_nomos[8:0]:sdram_a_mos[8:0])};
assign tn[2:0]=raddr[8:6];
assign inc_sdrama=(sdram_an[8:0]!=0) || (sdram_rdy && this_rdy && !pend_next && ccv_start_en);
assign avr[7:0]=avm_q[7:0];
wire first_cell, first_in_row, nineth_in_row,afterlast_in_row, nineth_row;
SRL16 i_nineth_in_row (.Q(nineth_in_row), .A0(1'b1), .A1(1'b1), .A2(1'b1), .A3(1'b0), .CLK(clk), .D(first_in_row));
SRL16 i_afterlast_in_row(.Q(afterlast_in_row),.A0(1'b1), .A1(1'b0), .A2(1'b0), .A3(1'b1), .CLK(clk), .D(nineth_in_row));
// writing accumulators to memory (to subract from the output data)
always @ (posedge clk) begin
avm_we <=((caddrw[5:0]==6'h3f) && cwe) || // accCb, accCr;
(yaddrw[5:0]==6'h3f); // accYA,accYB (twice) - still OK as ywe is always 1 then
avm_a[2:0] <= ((caddrw[5:0]==6'h3f) && cwe)?{2'b10,caddrw[6]}:{1'b0,yaddrw[7:6]};
end
always @ (posedge clk)
if (!en_sdc || ccv_start || (ywe &&(yaddrw[7:0]==8'h78))) accYA <=14'h0; // just 1 cycle with 8'h78, OK
else if (ywe && (yaddrw[6]==1'b0)) accYA[13:0] <= accYA[13:0]+ y_in[7:0];
always @ (posedge clk)
if (!en_sdc || ccv_start || (ywe &&(yaddrw[7:0]==8'h80))) accYB <=14'h0; //8'h80 - 3 cycles, but still OK
else if (ywe && (yaddrw[6]==1'b1)) accYB[13:0] <= accYB[13:0]+ y_in[7:0];
always @ (posedge clk)
if (!en_sdc || cs_pre_first_out) accCb <=14'h0;
else if (cwe && (caddrw[6]==1'b0)) accCb[13:0] <= accCb[13:0]+ c_in[7:0];
always @ (posedge clk)
if (!en_sdc || cs_pre_first_out) accCr <=14'h0;
else if (cwe && (caddrw[6]==1'b1)) accCr[13:0] <= accCr[13:0]+ c_in[7:0];
assign avm_d= avm_a[2]?
(avm_a[0]?accCr[13:6]:accCb[13:6]):
(avm_a[0]?accYB[13:6]:accYA[13:6]);
always @ (posedge clk) avm_s[2:0] <= raddr[8:6];
RAM16X1D i_avermem0 (.DPO(avm_q[0]),.A0(avm_a[0]),.A1(avm_a[1]),.A2(avm_a[2]),.A3(1'b0),.D(avm_d[0]),
.DPRA0(avm_s[0]),.DPRA1(avm_s[1]),.DPRA2(avm_s[2]),.DPRA3(1'b0),.WCLK(clk),.WE(avm_we));
RAM16X1D i_avermem1 (.DPO(avm_q[1]),.A0(avm_a[0]),.A1(avm_a[1]),.A2(avm_a[2]),.A3(1'b0),.D(avm_d[1]),
.DPRA0(avm_s[0]),.DPRA1(avm_s[1]),.DPRA2(avm_s[2]),.DPRA3(1'b0),.WCLK(clk),.WE(avm_we));
RAM16X1D i_avermem2 (.DPO(avm_q[2]),.A0(avm_a[0]),.A1(avm_a[1]),.A2(avm_a[2]),.A3(1'b0),.D(avm_d[2]),
.DPRA0(avm_s[0]),.DPRA1(avm_s[1]),.DPRA2(avm_s[2]),.DPRA3(1'b0),.WCLK(clk),.WE(avm_we));
RAM16X1D i_avermem3 (.DPO(avm_q[3]),.A0(avm_a[0]),.A1(avm_a[1]),.A2(avm_a[2]),.A3(1'b0),.D(avm_d[3]),
.DPRA0(avm_s[0]),.DPRA1(avm_s[1]),.DPRA2(avm_s[2]),.DPRA3(1'b0),.WCLK(clk),.WE(avm_we));
RAM16X1D i_avermem4 (.DPO(avm_q[4]),.A0(avm_a[0]),.A1(avm_a[1]),.A2(avm_a[2]),.A3(1'b0),.D(avm_d[4]),
.DPRA0(avm_s[0]),.DPRA1(avm_s[1]),.DPRA2(avm_s[2]),.DPRA3(1'b0),.WCLK(clk),.WE(avm_we));
RAM16X1D i_avermem5 (.DPO(avm_q[5]),.A0(avm_a[0]),.A1(avm_a[1]),.A2(avm_a[2]),.A3(1'b0),.D(avm_d[5]),
.DPRA0(avm_s[0]),.DPRA1(avm_s[1]),.DPRA2(avm_s[2]),.DPRA3(1'b0),.WCLK(clk),.WE(avm_we));
RAM16X1D i_avermem6 (.DPO(avm_q[6]),.A0(avm_a[0]),.A1(avm_a[1]),.A2(avm_a[2]),.A3(1'b0),.D(avm_d[6]),
.DPRA0(avm_s[0]),.DPRA1(avm_s[1]),.DPRA2(avm_s[2]),.DPRA3(1'b0),.WCLK(clk),.WE(avm_we));
RAM16X1D i_avermem7 (.DPO(avm_q[7]),.A0(avm_a[0]),.A1(avm_a[1]),.A2(avm_a[2]),.A3(1'b0),.D(avm_d[7]),
.DPRA0(avm_s[0]),.DPRA1(avm_s[1]),.DPRA2(avm_s[2]),.DPRA3(1'b0),.WCLK(clk),.WE(avm_we));
assign first_cell=(sdram_an[8:0]==0) && (sdram_rdy && this_rdy && !pend_next && ccv_start_en);
assign first_in_row=en && inc_sdrama && (first_cell || afterlast_in_row);
assign nineth_row= (sdram_an[7:4]==4'ha);
wire [8:0] sdram_an_plus1= sdram_an[8:0]+1;
wire [1:0] sdram_an_bank1= sdram_an[10:9]+1;
wire [8:0] sdram_a_mos_nxt=sdram_a_mos[8:0]+((line18[4:0]==5'h11)?3:1);
always @ (posedge clk) begin
/*
if (!en) sdram_an[9:0] <=10'b0;
else if (inc_sdrama) sdram_an[9:0] <=
(sdram_an[8] && sdram_an[6] && sdram_an[1] && sdram_an[0])?
{~sdram_an[9],9'b0}:
{sdram_an[9],sdram_an_plus1[8:0]}; //last is 323='h143
*/
if (!en) sdram_an[10:0] <=11'b0;
else if (inc_sdrama) sdram_an[10:0] <=
(sdram_an[8] && sdram_an[6] && sdram_an[1] && sdram_an[0])?
{sdram_an_bank1[1:0],9'b0}:
{sdram_an[10:9],sdram_an_plus1[8:0]}; //last is 323='h143
if (!en) line18[4:0] <=5'b0;
else if (inc_sdrama) line18[4:0] <= (line18[4:0]==5'h11)?5'b0:line18[4:0]+1;
if (!en) sdram_a_mos[8:0] <=9'b0;
else if (inc_sdrama) sdram_a_mos[8:0] <=
(sdram_an[8] && sdram_an[6] && sdram_an[1] && sdram_an[0])?
9'b0:{sdram_a_mos_nxt[8:0]};
// needs updating!!!!!!!!!!!!
// first_next_row<=last_in_row;
/* if (first_cell) sdram_a_nomos[8:0] <= 9'h1ef;
else if (inc_sdrama) sdram_a_nomos[8:0] <= sdram_a_nomos[8:0] +
(afterlast_in_row?
(nineth_row? 9'h103:9'h011):
(nineth_in_row?9'h1f3:9'h002));
*/
if (first_cell) sdram_a_nomos[8:0] <= 9'h1ed;
else if (inc_sdrama) sdram_a_nomos[8:0] <= sdram_a_nomos[8:0] +
(afterlast_in_row?
(nineth_row? 9'h0e7:9'h015):
(nineth_in_row?9'h1f3:9'h002)); //same
ccv_start_en <= en && (ccv_start_en || go);
/*+*/ ccv_start <= (sdram_an[8:0]==9'h024);
/*+*/ tim2next <= (sdram_an[8:0]==9'h13f); // rather arbitrary number - sdram buffer should in no case be actually overwritten before data read out
// it may depend on relation between SDRAM clk frequency (75MHz) and this clk (variable? 30MHz)
tim2next1 <= tim2next;
if (!en || sdram_next) pend_next <=1'b0;
else if (tim2next) pend_next <=1'b1;
sdram_next <= pend_next && ((bcntr[15:0]!=16'b0) || (go && (!go_d || tim2next1))) && ~sdram_next;
eot <= tim2next1 && (bcntr[15:0]==16'b0);
go_d <= go;
go_ds <= go && !go_d;
if (go_ds || (go && eot)) bcntr[15:0] <= nblocks[15:0];
else if (sdram_next) bcntr[15:0] <= bcntr[15:0]-1;
/*+*/ if (ccv_start) wpage <= sdram_an[9]; // copy page from SDRAM buffer
// increase latency for average value calculation
// ccv_out_start <=(yaddrw[7:0]==8'h7f); // fine tune? 64 cycle before first tile is finished
/*+*/ ccv_out_start <=(yaddrw[7:0]==8'hc5); // fine tune? 64 cycle before first tile is finished
if (ccv_out_start) rpage <=wpage;
if (ccv_out_start || !en) raddr[8:0] <= {!en,!en,7'h0}; // 9'h180/9'h000;
else if (raddr[8:7]!=2'b11) raddr[8:0] <= raddr[8:0]+1;
dv0 <= (raddr[8:7]!=2'b11);
ds0 <= (raddr[8:7]!=2'b11) && (raddr[5:0]==6'b0);
buf_sel <= raddr[8];
pre_do[8:0] <= (buf_sel?c_out[7:0]:y_out[7:0])-avm_q[7:0];
do[8:0] <= pre_do[8:0];
// now deal with this_rdy - adjust from simulation to make period exactly 384 cycles
if (!en || (raddr[8:0]==9'h0b4)) this_rdy <=1'b1; // ** 9'h0b4 - minimal value
else if (ccv_start) this_rdy <=1'b0;
dv_raw <= inc_sdrama && en;
if (go_ds || (go && eot)) willbe_first <= 1'b1;
else if (ccv_start) willbe_first <= 1'b0;
if (ccv_start) begin
first0 <= willbe_first;
last0 <= (bcntr[15:0]==16'b0);
end
if (ccv_out_start) begin
first <= first0;
last <= last0;
end
end
SRL16 i_dv (.Q(dv), .A0(1'b1), .A1(1'b0), .A2(1'b0), .A3(1'b0), .CLK(clk), .D(dv0)); // dly=1+1
SRL16 i_ds (.Q(ds), .A0(1'b1), .A1(1'b0), .A2(1'b0), .A3(1'b0), .CLK(clk), .D(ds0)); // dly=1+1
csconvert i_csconvert (.RST(!en),
.CLK(clk),
.mono(ignore_color),
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -