|
发表于 2009-11-29 20:31:32
|
显示全部楼层
贴点代码吧。只是部分代码,初学者,全贴太丢人了。。。
大概的原理就是,用时钟驱动计数器,根据计数器的值发送数据到屏上
为了简单,内存占用比较浪费。4字节数据只用其中3个字节。
//产生VSYNC和HSYNC计数
reg [11:0]HSYNC_cnt, VSYNC_cnt;
always @ (posedge LCD_DCLK)
begin
if (reset || !CONFIG_Display_en)
begin
HSYNC_cnt <= 12'd0;
VSYNC_cnt <= 12'd0;
end
else if (HSYNC_cnt < LCDCFG_tHP)
begin
HSYNC_cnt <= HSYNC_cnt + 12'd1;
VSYNC_cnt <= VSYNC_cnt;
end
else if (VSYNC_cnt < LCDCFG_tVP)
begin
HSYNC_cnt <= 12'd0;
VSYNC_cnt <= VSYNC_cnt + 12'd1;
end
else
begin
HSYNC_cnt <= 12'd0;
VSYNC_cnt <= 12'd0;
end
end
DE根据计数器的值判断是否需要传输数据到屏上
wire HoriValid;//有效像素
wire VertValid;//有效行
assign VertValid = (VSYNC_cnt >= LCDCFG_tVW + LCDCFG_tVBP) && (VSYNC_cnt < LCDCFG_tVW + LCDCFG_tVBP + LCDCFG_tW);
assign HoriValid = VertValid && (HSYNC_cnt >= LCDCFG_tHW + LCDCFG_tHBP) && (HSYNC_cnt < LCDCFG_tHW + LCDCFG_tHBP + LCDCFG_tHV);
always @ (posedge LCD_DCLK)
begin
if (reset || !CONFIG_Display_en)
begin
LCD_DE_m <= 0;
LCD_RED_m <= 8'b0;
LCD_GREEN_m <= 8'b0;
LCD_BLUE_m <= 8'b0;
end
else if (HoriValid)//传输像素数据到LCD
begin
LCD_DE_m <= 1;
LCD_RED_m <= LCDFIFO_rddata[7:0];
LCD_GREEN_m <= LCDFIFO_rddata[15:8];
LCD_BLUE_m <= LCDFIFO_rddata[23:16];
end
else
begin
LCD_DE_m <= 0;
LCD_RED_m <= 8'b0;
LCD_GREEN_m <= 8'b0;
LCD_BLUE_m <= 8'b0;
end
end
我用一个FIFO存储需要发到屏上的像素。随时补充新数据进去。
reg [11:0]CurrentReadLine, data_reqline;
//本地总线读取控制 当FIFO数据不足时请求传输下一行的数据
always @ (posedge clk)
begin
if (reset || !CONFIG_Display_en)
begin
data_req <= 0;
LCDFIFO_clrreq <= 1;
CurrentReadLine <= 12'd0;
data_reqline<= 12'd0;
end
else if (VSYNC_cnt == 12'd0)//当扫描回到0行的时候清空FIFO。
begin
data_req <= 0;
LCDFIFO_clrreq <= 1;
CurrentReadLine <= 12'd0;
data_reqline<= 12'd0;
end
else if (data_req && !data_idle)
begin
data_req <= 0;
end
else if (!data_req && data_idle && (LCDFIFO_wrusedw < LCDCFG_tHV) && (CurrentReadLine < LCDCFG_tW))//判断接口空闲 FIFO数据不足
begin
data_req <= 1;
LCDFIFO_clrreq <= 0;
CurrentReadLine <= CurrentReadLine + 12'd1;
data_reqline<= CurrentReadLine;
end
else
begin
end
end
//FIFO 2048字*32bit,CYCLONE III需要占用8个M9K存储器块。
wire [31:0]LCDFIFO_rddata;
wire [11:0]LCDFIFO_wrusedw;
reg LCDFIFO_clrreq;
LCD_FIFO (
.aclr(reset || LCDFIFO_clrreq),
.data(data_wrdata),
.rdclk(LCD_DCLK),
.rdreq(HoriValid),
.wrclk(clk),
.wrreq(data_wren),
.q(LCDFIFO_rddata),
.rdempty(),
.rdusedw(),
.wrempty(),
.wrfull(),
.wrusedw(LCDFIFO_wrusedw));
我用的LCD时序
//LCD时序配置
parameter
LCDCFG_tHV = 800, //Horizontal valid data width
LCDCFG_tW = 480, //Vertical valid data width
LCDCFG_tHP = 928, //HSYNC Period
LCDCFG_tHW = 48, //HSYNC Pulse Width
LCDCFG_tHBP = 40, //HSYNC Back Porch
LCDCFG_tVP = 525, //VSYNC Period
LCDCFG_tVW = 3, //VSYNC Pulse Width
LCDCFG_tVBP = 29; //VSYNC Back Porch
这是根据计数器产生VSYNC和HSYNC信号,但似乎时序上有问题。虽可显示图像,但图像位置不正确。尚不知道怎么计算正确的时序。。。
//产生VSYNC和HSYNC计数 根据计数产生相应的时序
reg [11:0]HSYNC_cnt, VSYNC_cnt;
always @ (posedge LCD_DCLK)
begin
if (reset || !CONFIG_Display_en)
begin
HSYNC_cnt <= 12'd0;
VSYNC_cnt <= 12'd0;
end
else if (HSYNC_cnt < LCDCFG_tHP)
begin
HSYNC_cnt <= HSYNC_cnt + 12'd1;
VSYNC_cnt <= VSYNC_cnt;
end
else if (VSYNC_cnt < LCDCFG_tVP)
begin
HSYNC_cnt <= 12'd0;
VSYNC_cnt <= VSYNC_cnt + 12'd1;
end
else
begin
HSYNC_cnt <= 12'd0;
VSYNC_cnt <= 12'd0;
end
end |
|