⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 color_proc333.v

📁 基于fpga的MJPEG编码,用硬件描述语言vlogic写的
💻 V
📖 第 1 页 / 共 3 页
字号:
/*
** -----------------------------------------------------------------------------**
** 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 + -