歡迎您光臨本站 登入註冊首頁

概述

一、設計目標:   設計一個LCD控制器,該控制器基於Altera的SOPC系統,通過SOPC中的Avalon匯流排介面與NiosII處理器和SDRAM控制器通信,使之能……

一、設計目標
    設計一個LCD控制器,該控制器基於Altera的SOPC系統,通過SOPC中的Avalon匯流排介面與Nios II處理器和SDRAM控制器通信,使之能顯示640*480解析度,顯示顏色深度達到16bit,輸出介面兼容TFT LCD。

二.設計原理
1、系統工作原理:
    如圖1所示,Nios II處理器在SDRAM中開闢framebuffer,可以是單緩衝也可以是雙緩衝,以單緩衝為例。Nios II處理器將一幀圖象數據(640×480×2Bytes,RGB565,16bit)存入framebuffer,然後將framebuffer的首地址寫入到LCD控制器,並啟動LCD控制器,該控制器自動從傳來的首地址處開始讀取圖象數據,並按照TFT的格式輸出。
 
    圖中各模塊由Avalon Bus連接在一起。Avalon Bus是一種簡單的匯流排結構,在SOPC中,Nios II軟核處理器和各種外設都通過Avalon Bus連接在一起。由圖1可以看出,作為Slaver的SDRAM Controller分別要受到Processor 和LCD Controller的控制,為了解決匯流排衝突,Avalon Bus自動在有衝突的介面上加入了Arbitrator這樣一個仲裁模塊,用於合理分配匯流排時間,用戶通過改變每個模塊的權值來改變對其分配匯流排時間的多少。在這個系統中,SDRAM Controller處的衝突是影響整個系統性能的關鍵。以SDRAM時鐘頻率為100MHz計算,16bit位寬的SDRAM其數據總帶寬為200MByte/s,640*480*2Bytes*60Hz的TFT LCD要佔用36MByte/s左右的帶寬,這對於還要處理其他任務的處理器來說是很大的影響。解決的辦法是另外增加一塊SDRAM,專門用作Frame buffer,這樣就可以有效減少對系統匯流排帶寬的佔用。

2、LCD Controller工作原理
    如圖2所示,LCD Controller主要由Avalon 匯流排介面、寄存器組、控制模塊、DMA、FIFO以及時序生成模塊組成。每個寄存器獨立編址,處理器可以通過匯流排讀寫存儲器的方式來訪問。處理器通過Avalon匯流排接讀寫寄存器,從而完成對LCD控制器工作狀態的設定與控制。
 
    控制器啟動后,DMA Master通過avalon匯流排讀取SDRAM中的數據,然後存入FIFO中,時序生成模塊按照TFT時序要求從FIFO中讀取數據,然後送出去顯示。整個數據讀取過程不需要處理器干涉,實際上是一個DMA過程。
    考慮到DMA讀取的速度與TFT時序發生器輸出的速度不一致(前者大於後者),所以在DMA與TFT時序發生器之間加入了FIFO用來緩衝數據。DMA有控制模塊控制其工作。控制模塊不斷檢測FIFO狀態,當FIFO快滿時,暫停DMA,當FIFO快空時,重新啟動DMA,如此循環,可保證FIFO不溢出,保證顯示畫面連續穩定。

三、設計細節
1、Avalon Bus Slaver從匯流排介面
Avalon從匯流排介面負責處理器與LCD控制器的介面控制,LCD控制器在整個系統中作為從設備,通過該介面,接受CPU的控制。根據設計需要,該介面所需要的各信號為:

input:  
chipselect 片選,高電平有效
Write_n 寫信號,低電平有效
Read_n 讀信號,低電平有效
Reset_n 複位,低電平有效
clk 系統時鐘
address[1:0] 地址信號
writedata[31:0] 寫數據
output:  
readdata[31:0] 讀數據
irq_n 中斷請求,低電平有效

這些信號均要求滿足Avalon匯流排的時序要求:(採用基本時序)
讀時序:
 
    如圖3所示,讀時序在一個系統時鐘周期內完成。在第一個clk上升沿,系統將address、byteenable、read信號輸出到從設備介面,系統內部對address進行地址解碼,生成chipselect信號也傳輸到從設備介面,一旦chipselect被置高,從設備立即將readdata信號輸出到從設備介面,系統在第二個時鐘上升沿讀取該數據,從而完成一次讀操作。
    為滿足此時序,可利用第一個clk的下降沿來檢測address、read、chipselect信號是否有效,如果有效,立即輸出數據。
代碼如下:
always @(posedge slave_clk or negedge reset_n)
begin
if(reset_n == 0)
begin
slave_readdata<=0;
end
else if(slave_chipselect && ~slave_read_n)
begin
case(slave_address)
2''b00:
slave_readdata<=controlReg;
2''b01:
slave_readdata<=interStatus;
2''b10:
slave_readdata<=startAddress;
2''b11:
slave_readdata<=addressCounter;
endcase
end

寫時序:
 
    如圖4所示,寫操作也在一個時鐘周期內完成。在第一個clk上升沿,系統設置address、byteenable、writedata、write信號有效,然後內部將address信號解碼得出chipselect信號並立即傳輸到從設備介面,從設備在第二個clk上升沿捕獲介面上的數據,從而完成一個寫操作。
    為滿足此時序,從設備介面在第二個clk上升沿檢測address、write、chipselect信號是否有效,若有效,則將數據口上的數據writedata寫入到內部寄存器。
代碼如下:
always @(posedge slave_clk or negedge reset_n)
begin
if(reset_n == 0)
begin
controlReg<=0;
//
statusReg<=0;
startAddress<=0;
frameLength<=0;
end
else if(slave_chipselect && ~slave_write_n)
begin
case(slave_address)
2''b00:
controlReg<=slave_writedata;

//2''b01:
statusReg<=slave_writedata;
2''b10:
startAddress<=slave_writedata;
2''b11:
frameLength<=slave_writedata;
endcase
end
end
clk信號為系統時鐘信號,這裡取100MHz。
reset_n為複位信號,低電平有效,複位后,LCD控制器應該處於一個設定好的狀態。
irq為中斷請求信號,當控制器滿足下列條件之一時,向系統發出中斷請求信號,將irq信號置高,直到系統響應該信號,並用軟體將其清零。(暫時未使用)

2、Avalon Bus DMA Master主設備介面
    Avalon Bus DMA Master負責按照控制模塊的指令,讀取SDRAM中的數據,並寫入到FIFO中。其核心部分是DMA地址累加器,當條件滿足時,地址累加器開始在100MHz的時鐘下以4為單位開始累加(為何以4為單位,是由avalon匯流排的地址映射方式決定的。avalon匯流排按位元組進行編址,而SDRAM控制器一次讀取32bit即4Byte的數據,所以地址要以4為單位累加),用於生成讀取SDRAM的地址。讀完一幀的數據后,自動複位到首地址,繼續累加。
主設備介面信號列表:

input:  
Master_clk 主設備時鐘100MHz
Master_waitrequest 主設備等待信號
Master_readdatavalid 主設備數據有效信號
Master_readdata[31:0] 主設備數據
Output:  
Master_read_n 主設備讀信號
Master_address[31:0] 主設備地址信號

主設備介面時序:
 
    如圖5所示,主設備介面採用帶延遲的主設備讀傳輸模式,在這種傳輸模式下,即使沒有接收到上一次的有效數據,主設備也可以發起下一次讀命令。當waitrequest信號無效(低電平)時,主設備可以連續的發起讀命令,當waitrequest信號有效(高電平)時,主設備開始等待,知道其變為低電平。當readdatavalid信號有效(高電平)時,表示讀數據有效,此時主設備可以鎖存數據口上的有效數據。這裡我們沒有使用flush信號,flush信號會清楚前面一切未完成的讀命令。Avalon匯流排保證數據的輸出順序與主設備要求的順序一致(即與主設備地址輸出順序一致)。readdatavalid信號可以作為FIFO的wrreq信號,這樣可以直接將讀回來的數據寫入到FIFO中。
    地址累加器滿足以下條件時,則開始累加,噹噹前地址等於尾地址時,則複位累加器,使之重新開始從首地址累加:
1)、非FIFO快滿(即fifo_almostfull信號無效)
2)、master_waitrequest無效
地址累加器代碼:
wire[31:0] endAddress;
reg[31:0] addressCounter;
wire addressCounter_sload;
wire addressCounter_inc;
assign endAddress=startAddress+frameLength;
assign addressCounter_sload=(~controller_GoBit) | (addressCounter == endAddress);
assign addressCounter_inc=(~master_read_n) & (~master_waitrequest) &(controller_GoBit);
assign master_address=addressCounter;
assign master_read_n=~(fifo_almostfull ^ controller_GoBit);
always @(posedge master_clk or negedge reset_n)
begin

if(reset_n == 0)
begin
addressCounter<=0;
end
else if(addressCounter_sload == 1)
begin
addressCounter<=startAddress;
end
else if(addressCounter_inc == 1)
begin
// address incs as 0,4,8,16,...
addressCounter<=addressCounter+4;
end
end

3、FIFO(先入先出存儲器)
    FIFO的作用是對DMA輸出的圖象數據進行緩存,以匹配時序控制模塊的輸出速度。FIFO大小暫定為4096*16bit,在實際設計時,再根據系統需要以及資源狀況作出適當調整,原則是,在系統資源允許的情況下,將FIFO大小盡量設置大點。
    FIFO由DMA控制器寫入數據,寫入時鐘為100MHz;由LCD控制器的時序發生模塊讀出數據,讀出時鐘為PCLK,即LCD的象素點掃描頻率,通常取25MHz。在獨立的寫時鐘和讀時鐘作用下,FIFO可以提供rdusedw[11:0]信號,用於指示FIFO中已經使用掉的容量。系統可以設置一個上限和一個下限,當FIFO中的數據量高於上限或低於下限時,控制器暫停DMA傳輸或啟動DMA傳輸,用以保證系統性能。
下圖是該FIFO的讀寫時序圖。
 
    在本例應用中,將wrclk接系統時鐘(100MHz),wrreq接master_readdatavalid,data接writedata,即可完成DMA的數據寫入操作;將rdclk接12.5MHz(因為TFT的時鐘為25MHz,數據寬度為16bit,而FIFO的寬度為32bit,所以用一半的時鐘12.5MHz去讀取FIFO,然後依次輸出32bit的高16bit和低16bit),rdreq由時序發生模塊控制,即可在每個rdclk的上升沿讀出一個數據到q。aclr接~reset_n,可以完成複位操作。當然,所有信號都受controller_GoBit的控制。
FIFO代碼如下:
assign fifo_aclr=(~reset_n) | (~controller_GoBit);
assign fifo_wrdata=master_readdata;
assign fifo_wrclk=master_clk;
assign fifo_wrreq=master_readdatavalid & controller_GoBit;
assign fifo_rdclk=clk_12M;
assign tft_data[15:0]=clk_12M ? fifo_rddata[31:16] : fifo_rddata[15:0];
lcd_fifo lcd_fifo_0(
.aclr(fifo_aclr),
.data(fifo_wrdata),
.rdclk(fifo_rdclk),
.rdreq(fifo_rdreq),
.wrclk(fifo_wrclk),
.wrreq(fifo_wrreq),
.q(fifo_rddata),
.wrusedw(fifo_wrusedw)
);

4、Registers(寄存器組)
為了簡化設計,本例只設置四個32bit的可讀寫寄存器,用於控制LCD控制器的工作和指示其工作狀態。
controlReg 控制寄存器,用於控制LCD控制器的運行與停止
statusReg  狀態寄存器,用於指示LCD控制器的工作狀態(保留)
startAddress DMA首地址,即緩衝區首地址
frameLength 幀長度

5、Control(控制模塊)
       控制模塊用於協調LCD控制器各部分的工作,用於連接寄存器組與時序發生器。在實際的設計中並沒有獨立的這麼一個控制模塊,各種控制關係實際上已經集成到各個分模塊裡面去了。

6、LCD Timing Generator(LCD顯示時序發生器)
    時序發生器用於產生TFT屏幕所需的時序,將圖象數據按特定的時序輸出。本設計專門針對三菱公司的AA084VC05液晶屏設計,下面是其時序分析:

  
    LCD時序發生器以DCLK為時鐘基準,該DCLK即上面所說的PCLK,也就是像點時鐘,每個象素點的數據以該時鐘驅動進入LCD。如上圖所示,為AA084VC05的水平掃描時序,其中,DATA為18位數據信號(本設計中只用其中的16位),DENA為數據有效信號,高電平使能,其有效寬度THA為640個DCLK;HD為水平同步信號,低電平有效,其有效寬度TWHL為96個DCLK。一行640個象素掃描完畢之後,控制器將驅動HD有效,在HD有效之前插入THFP(Horizontal Front Porch)為16個DCLK,有效之後插入THBP(Horizontal Back Porch)為144個DCLK,然後再開始下一行的掃描。如此一來,行掃描信號的頻率FH典型值為31.5KHz。而讀FIFO信號要提前DENA信號一個時鐘節拍到來,提前一個時鐘節拍結束,因為該FIFO有一個時鐘節拍的延遲。
       AA084VC05的垂直掃描時序與水平掃描時序類似,該時序以HD為時鐘基準,其中,VD為垂直同步信號(幀同步)。每掃描完一幀(480行),控制器將驅動VD有效(低電平),有效寬度TWVL為2個HD。同樣,在VD有效之前插入TVFP(Vertical Front Porch)為10個HD,有效之後插入TVBP(Vertical Back Porch)為35個HD,如此一來,垂直掃描信號頻率FV的典型值為60Hz。
    在本設計中,所有這些時序參數都用parameter來表示,在以後更一般化的設計中,這些參數將由寄存器組來設置。
parameter LINES= 480;
//Number of lines
parameter COLUMNS = 640;
//Pixel Number Per Line
parameter THFP= 16;
// Horizontal Front Porch(DCLK)
parameter THBP= 144;
// Horizontal Back Porch(DCLK)
parameter TWHL= 96;
// Horizontal Low Width(DCLK)
parameter TVFP= 10;
// Vertical Front Porch(HD)
parameter TVBP= 35;
// Vertical Back Porch(HD)
parameter TWVL= 2;
// Vertical Low Width(HD)
時序發生器採用狀態機實現,如下代碼:
reg oHSYNC;
reg oVSYNC;
reg oDENA;
reg lineENA;
reg[9:0] cCounter;
reg[9:0] lCounter;
assign oSC= 0;
assign oPCLK = clk_25M;
assign oPDATA =oDENA ? {tft_data[15:11],1''b0,tft_data[10:0],1''b0} : 18''hz;
//horizontal sync signal generator
always @(posedge clk_25M)
begin
if(tft_reset_n == 0)
//reset active
begin
oDENA<=0;
oHSYNC<=0;
cCounter[9:0]<=0;
fifo_rdreq<=0;
end
else if(tft_GoBit == 1)
begin
case(cCounter)
0:
begin
oHSYNC<=0;
cCounter<=cCounter + 1;
end
TWHL - 1:
begin
oHSYNC<=1;
cCounter<=cCounter + 1;
end
THBP - 2:
begin
//generate the fifo read request signal,
//sets earlier for 1 clock than oDENA
fifo_rdreq<=lineENA & tft_GoBit;
cCounter<=cCounter + 1;
end
THBP - 1:
begin
oDENA<=lineENA & tft_GoBit;
//only when lineENA active then oDENA active
cCounter<=cCounter + 1;
end
THBP + COLUMNS - 2:
begin
//fifo read request signal ends earlier for 1 clock than oDENA
fifo_rdreq<=0;
cCounter<=cCounter + 1;
end
THBP + COLUMNS - 1:
begin
oDENA<=0;
cCounter<=cCounter + 1;
end
THBP + COLUMNS + THFP - 1:
begin
oHSYNC<=0;
cCounter<=0;
end
default:
cCounter<=cCounter + 1;
endcase
end
end

//vertical sync signal generator
always @(negedge oHSYNC)
begin
if(tft_reset_n == 0)
//reset active
begin
lineENA<=0;
oVSYNC<=0;
lCounter[9:0]<=0;
end
else if(tft_GoBit == 1)begin
case(lCounter)
0:
begin
oVSYNC<=0;
lCounter<=lCounter + 1;
end
TWVL - 1:
begin
oVSYNC<=1;
lCounter<=lCounter + 1;
end
TVBP - 1:
begin
lineENA<=1;
lCounter<=lCounter + 1;
end
TVBP + LINES - 1:
begin
lineENA<=0;
lCounter<=lCounter + 1;
end
TVBP + LINES + TVFP - 1:
begin
oVSYNC<=0;
lCounter<=0;
end
default:
lCounter<=lCounter + 1;
endcase
end
end

四、設計總結
    本文設計實現了一個簡單的基於Avalon匯流排的TFT LCD控制器,能實現640×480,顏色深度為16bit的彩色圖形顯示,可應用於各種TFT LCD,亦可改寫為VGA控制器。在SOPC系統的使用中,有較大的靈活性。同時,通過本設計的實現過程,我也從中學到了不少知識,對SOPC,對Avalon匯流排等的理解更深了一步。


[admin via 研發互助社區 ] 基於Avalon匯流排的TFT LCD 控制器的設計已經有4868次圍觀

http://cocdig.com/docs/show-post-43086.html