東芝線陣CCD芯片TCD1305DG驅動時序設計


最近在做微型光譜儀,用到了東芝的CCD芯片TCD1305DG,該芯片是單行3648像素,輸出信號是時間上離散的模擬信號,典型輸出速率為0.5M,即每2000ns輸出一個像素值(模擬信號),芯片內部集成了相關雙采樣電路,直接輸出穩定的像元電壓值,而不是傳統的三階梯信號。TCD1305DG需要三路驅動信號,分別是主時鍾CLK,移位輸出信號SH,積分清除信號ICG,芯片手冊上給出的時序波形如下:

image

圖1 TCD1305DG驅動時序

該CCD的基本工作原理如下:光敏元接收外部光信號並將其轉換為電荷儲存在光敏元下方的電子勢阱中,當積分清除柵ICG為低電平時,如果檢測到轉移柵SH信號下降沿,就會將電子勢阱中積累的電荷轉移到模擬移位寄存器中,等待ICG回到高電平后,模擬移位寄存器中的電荷就在主時鍾CLK作用下逐個的輸出到OS管腳上,每四個主時鍾周期輸出一個像素電壓值,所以ICG的高電平的持續時間需保證所有的像素電荷都已經輸出,故ICG的高電平持續時間稱為轉移時間。而ICG低電平時SH的下降沿到SH的前一個下降沿之間的時間間隔稱為積分時間(如圖2所示),在這段時間里光敏元不斷地積累電荷,線陣CCD的成像效果與積分時間有着密切的關系。

image

圖2 積分時間示意圖

一. TCD1305DG驅動時序設計

本設計中根據TCD1305DG芯片手冊將積分時間設為50us,主時鍾周期為500ns,取圖1中的t2為500ns,t3為2500ns,ICG低電平持續時間為8000ns,ICG高電平期間輸出3696個像素值(實際上只有3694個像素,此處取為3696是為了與SH信號同步:3696 X (500 X 4) + 8000 = N*50us)。三路驅動信號的波形圖設計如下:

時序參數圖

圖3 驅動信號波形設計參數

下面分別介紹這三路信號的產生方法:

1. 主時鍾CLK

主時鍾CLK周期為2M,可以直接對晶振分頻得到,此處采用100M晶振,對其50分頻就可以得到2M的時序信號,設計verilog代碼如下:

//------------generate CCD_CLK, 2M-------------------
reg [5:0] cnt_clk;
always @ (posedge clk or negedge rst_n)
if(!rst_n)
    cnt_clk <= 6'd0;
else if(cnt_clk == 6'd49)  // 1/50 divide, 100M TO 2M
    cnt_clk <= 6'd0;
else    
    cnt_clk <= cnt_clk + 1'b1;

always @ (posedge clk or negedge rst_n)
if(!rst_n)
    CCD_CLK <= 1'b1;
else if(cnt_clk == 6'd25)
    CCD_CLK <= 1'B0;
else if(cnt_clk == 6'd0)
    CCD_CLK <= 1'B1;
//--------------------------------------------------

 

2. 移位信號SH

移位信號的周期就是積分時間,此處為50us,每個周期內的波形為500ns電平、2500ns高電平以及47000ns低電平(圖3),產生SH的方法如下:首先由晶振分頻產生周期為500ns的使能時鍾clk1,clk1的0-490ns為低,490-0ns為高;由clk1控制計數器 cnt_sh的變化,cnt_sh每500ns計一個數,計滿100個數后歸零,由cnt_sh就可以生成周期為50us的時序信號SH,具體過程如圖4所示:

SH生成方法

圖4 移位信號SH生成方法

根據以上原理設計verilog代碼如下:

//----------generate clk1, 490ns-low, 50ns-high-------
reg clk1;
always @ (posedge clk or negedge rst_n)
if(!rst_n)
    clk1 <= 1'b0;
else if(cnt_clk == 6'd49) 
    clk1 <= 1'b1;
else
    clk1 <= 1'b0;
//----------------------------------------------------

//----------generate SH ----------------------------
reg [6:0] cnt_sh;
always @ (posedge clk or negedge rst_n)
if(!rst_n)
    cnt_sh <= 7'd0;
else if((cnt_sh == 7'd99) && clk1)  // attention!! - clk1
    cnt_sh <= 7'd0;
else if(clk1)
    cnt_sh <= cnt_sh + 1'b1;
    
always @ (posedge clk or negedge rst_n)
if(!rst_n)
    SH <= 1'B0;
else if((cnt_sh == 7'd0) && clk1)
    SH <= 1'B1;
else if((cnt_sh == 7'd5) && clk1)
    SH <= 1'B0;
//--------------------------------------------------

 

3. 積分清除信號ICG

積分清除信號ICG的產生方法與SH的產生方法相同,由使能時鍾clk1控制cnt_icg的變化,再由cnt_icg生成ICG信號,具體過程參考圖4,此處僅給出對應的verilog代碼:

//------------generate ICG--------------------------
reg [13:0] cnt_icg;
always @ (posedge clk or negedge rst_n)
if(!rst_n)
    cnt_icg <= 14'd0;
else if((cnt_icg == 14'd14799) && clk1)
    cnt_icg <= 14'd0;
else if(clk1)
    cnt_icg <= cnt_icg + 1'b1;
    
always @ (posedge clk or negedge rst_n)
if(!rst_n)
    ICG <= 1'B1;
else if(cnt_icg == 14'd0)
    ICG <= 1'B0;
else if((cnt_icg == 14'd15) && clk1)  // 8000ns-low
    ICG <= 1'B1;
else if((cnt_icg == 14'd14799) && clk1) 
    ICG <= 1'B0;
//--------------------------------------------------

 

二. AD芯片AD9200驅動時序設計

從CCD輸出的光譜信號為時間上離散的模擬信號,經過AD轉換電路后轉換為數字信號輸出,本設計中的AD轉換芯片為AD9200,其驅動波形如下圖:

image

圖5 AD9200驅動波形

由圖可知,在芯片輸入時鍾的上升沿采集模擬信號,經過三個時鍾周期后,轉換后得到的數字信號將出現在輸出總線上,因此只需要為AD9200提供一個時鍾信號,其頻率與CCD輸出頻率一致,取為0.5MHz,當CCD輸出一個有效像素模擬信號時,經過三個時鍾周期,就可以在AD9200的輸出總線上得到這個有效像素的數字信號。

像素的輸出是在ICG的高電平期間進行的,所以可以將ICG的上升沿作為AD轉換的啟動信號,AD芯片的時鍾AD_CLK與像素的輸出速率一致,為0.5MHz,在AD_CLK的上升沿采集CCD輸出的模擬信號,設計AD_CLK的上升沿與輸出像素的中點對齊,如下圖所示:

AD轉換時序

圖6 AD轉換時序設計圖 

根據圖6設計verilog代碼如下:

//------------generate AD_CLK-----------------------
reg AD_START;
//start AD at posedge ICG, stop AD at negedge ICG
always @ (posedge clk or negedge rst_n)
if(!rst_n)
    AD_START <= 1'B0;
else if(cnt_icg == 14'd0)  //negedge ICG
    AD_START <= 1'B0;
else if((cnt_icg == 14'd15) && clk1)  // posedge ICG
    AD_START <= 1'B1;

reg [6:0] cnt_ad;
always @ (posedge clk or negedge rst_n)
if(!rst_n)
    cnt_ad <= 7'd0;
else if((cnt_ad == 7'd99) || !AD_START)  // 1/200 divide
    cnt_ad <= 7'd0;
else
    cnt_ad <= cnt_ad + 1'b1;

always @ (posedge clk or negedge rst_n)
if(!rst_n)
    AD_CLK <= 1'B0;
else if(cnt_ad == 7'd99)  // AD_CLK = 0.5M
    AD_CLK <= ~AD_CLK;
//-------------------------------------------------------

 

三. 完整的verilog代碼

下面給出完整的verilog代碼:

//CCD drive signal generate,
//output: CCD_CLK, SH, ICG
//2015/07/02

module sig_gen
(
    input clk,  //OSC = 100M
    input rst_n, //async reset
    output reg CCD_CLK,  //clock for CCD, 2M
    output reg SH,  
    output reg ICG,
    output reg AD_CLK  //clock for AD 
);

//------------generate CCD_CLK, 2M-------------------
reg [5:0] cnt_clk;
always @ (posedge clk or negedge rst_n)
if(!rst_n)
    cnt_clk <= 6'd0;
else if(cnt_clk == 6'd49)  // 1/50 divide, 100M TO 2M
    cnt_clk <= 6'd0;
else    
    cnt_clk <= cnt_clk + 1'b1;

always @ (posedge clk or negedge rst_n)
if(!rst_n)
    CCD_CLK <= 1'b1;
else if(cnt_clk == 6'd25)
    CCD_CLK <= 1'B0;
else if(cnt_clk == 6'd0)
    CCD_CLK <= 1'B1;
//--------------------------------------------------

//----------generate clk1, 490ns-low, 50ns-high-------
reg clk1;
always @ (posedge clk or negedge rst_n)
if(!rst_n)
    clk1 <= 1'b0;
else if(cnt_clk == 6'd49) 
    clk1 <= 1'b1;
else
    clk1 <= 1'b0;
//----------------------------------------------------

//----------generate SH ----------------------------
reg [6:0] cnt_sh;
always @ (posedge clk or negedge rst_n)
if(!rst_n)
    cnt_sh <= 7'd0;
else if((cnt_sh == 7'd99) && clk1)  // attention!! - clk1
    cnt_sh <= 7'd0;
else if(clk1)
    cnt_sh <= cnt_sh + 1'b1;
    
always @ (posedge clk or negedge rst_n)
if(!rst_n)
    SH <= 1'B0;
else if((cnt_sh == 7'd0) && clk1)
    SH <= 1'B1;
else if((cnt_sh == 7'd5) && clk1)
    SH <= 1'B0;
//--------------------------------------------------

//------------generate ICG--------------------------
reg [13:0] cnt_icg;
always @ (posedge clk or negedge rst_n)
if(!rst_n)
    cnt_icg <= 14'd0;
else if((cnt_icg == 14'd14799) && clk1)
    cnt_icg <= 14'd0;
else if(clk1)
    cnt_icg <= cnt_icg + 1'b1;
    
always @ (posedge clk or negedge rst_n)
if(!rst_n)
    ICG <= 1'B1;
else if(cnt_icg == 14'd0)
    ICG <= 1'B0;
else if((cnt_icg == 14'd15) && clk1)  // 8000ns-low
    ICG <= 1'B1;
else if((cnt_icg == 14'd14799) && clk1) 
    ICG <= 1'B0;
//--------------------------------------------------

//------------generate AD_CLK-----------------------
reg AD_START;
//start AD at posedge ICG, stop AD at negedge ICG
always @ (posedge clk or negedge rst_n)
if(!rst_n)
    AD_START <= 1'B0;
else if(cnt_icg == 14'd0)  //negedge ICG
    AD_START <= 1'B0;
else if((cnt_icg == 14'd15) && clk1)  // posedge ICG
    AD_START <= 1'B1;

reg [6:0] cnt_ad;
always @ (posedge clk or negedge rst_n)
if(!rst_n)
    cnt_ad <= 7'd0;
else if((cnt_ad == 7'd99) || !AD_START)  // 1/200 divide
    cnt_ad <= 7'd0;
else
    cnt_ad <= cnt_ad + 1'b1;

always @ (posedge clk or negedge rst_n)
if(!rst_n)
    AD_CLK <= 1'B0;
else if(cnt_ad == 7'd99)  // AD_CLK = 0.5M
    AD_CLK <= ~AD_CLK;
//-------------------------------------------------------


endmodule
以上代碼已經過仿真驗證,可以准確地生成CCD和AD的驅動時序。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM