搜索
bottom↓
回复: 38

50M晶振 EPM240 + 512KSRAM 做 800*600 TFT LCD 控制器

[复制链接]

出0入0汤圆

发表于 2010-8-3 18:44:49 | 显示全部楼层 |阅读模式
才接触Verilog,找了块人家的液晶转接板自己学习学习,也没钱打板子。

转接板上:

2跟地址线,8根数据线,CS,RD,WE信号与外部接口

LCDClk, Hsync Vsync, DE, R0,R1,R2, G0,G1,G2, B0,B1,驱动液晶,目前发现有问题在研究中……
希望有经验的大侠也一起帮忙指导。

主要是以前软件出身,难以一下转化到硬件语言的设计上来,纯技术交流!


把代码贴出来,一起调试:
module TFTDRV(
        input  GCLK,
        output TFT_CLK,
        output TFT_Hsync,
        output TFT_Vsync,
        output TFT_DE,
        output TFT_R0_3,
        output TFT_R1_4,
        output TFT_R2_5,
        output TFT_G0_3,
        output TFT_G1_4,
        output TFT_G2_5,
        output TFT_B0_2_4,
        output TFT_B1_3_5,
       
        output [19:0]RAM_A,
        inout  [7:0]RAM_D1,
        inout  [7:0]RAM_D2,
        output RAM_WE1,
        output RAM_WE2,

        inout  [7:0]EB_D,
        input  [1:0]EB_A,
        input  EB_CS,
        input  EB_WR,
        input  EB_RD,
        output EB_BUSY
);



reg        [7:0] reg_tft_rgb = 8'b00000000;
reg[19:0]reg_scan_addr = 20'd0;        //TFT LCD Scan Data Address

TFT_CTRL        U1(
  .INCLK(GCLK),
  .LCDCLK(TFT_CLK),
  .RGB(reg_tft_rgb),
  .Hsync(TFT_Hsync),
  .Vsync(TFT_Vsync),
  .DE(TFT_DE),
  .R0_3(TFT_R0_3),
  .R1_4(TFT_R1_4),
  .R2_5(TFT_R2_5),
  .G0_3(TFT_G0_3),
  .G1_4(TFT_G1_4),
  .G2_5(TFT_G2_5),
  .B0_2_4(TFT_B0_2_4),
  .B1_3_5(TFT_B1_3_5)
);


//RAM data inout port control
reg reg_ram_we1 = 1'b1;        //RAM Read=1/Write=0 Control Signal
reg [7:0]reg_ram_wdr1 = 8'b00000000;        //RAM Write Data Reg

assign RAM_D1 = (reg_ram_we1)?8'bzzzz_zzzz:reg_ram_wdr1;
assign RAM_WE1 = reg_ram_we1;


reg reg_ram_we2 = 1'b1;        //RAM Read=1/Write=0 Control Signal
reg [7:0]reg_ram_wdr2 = 8'b00000000;        //RAM Write Data Reg

assign RAM_D2 = (reg_ram_we2)?8'bzzzz_zzzz:reg_ram_wdr2;
assign RAM_WE2 = reg_ram_we2;

//reg[19:0]reg_ram_addr = 20'h00000;        //RAM Address Line
//assign RAM_A = reg_ram_addr;
reg reg_ram_idx = 1;
assign RAM_A = (reg_ram_idx)?reg_scan_addr:reg_cmd_addr;


//Extern Bus Command addres
reg[19:0]reg_cmd_addr = 20'd0;
reg [9:0]reg_cmd_x = 10'd0;
reg [9:0]reg_cmd_y = 10'd0;

parameter   XYHL_STA  = 1'b0;
parameter        XYHL_END = 1'b1;
reg reg_cmd_xyhl = XYHL_STA;        //Extern Bus Write X or Y High Or Low Byte


reg reg_rw_ram_flg = 1'b1;        //Read = 1; Write = 0;

reg reg_eb_wr_q1 = 1'b1;
reg reg_eb_wr_q2 = 1'b1;

reg reg_eb_rd_q2 = 1'b1;
reg reg_eb_rd_q1 = 1'b1;        //Extern Bus Read Signal
reg [7:0]reg_eb_dat =8'd0;
reg reg_eb_busy = 1'b1;        //Extern Bus Command Status

assign EB_D = reg_eb_rd_q2?8'bzzzz_zzzz:reg_eb_dat;
assign EB_BUSY = reg_eb_busy;

parameter        EBCMD_X = 2'b01;        //X address
parameter        EBCMD_Y = 2'b10;        //Y address
parameter        EBCMD_P = 2'b11;        //Page Select
parameter        EBCMD_C = 2'b00;        //Color data

always @ ( negedge GCLK )
begin
        if( TFT_CLK == 1 )
                reg_tft_rgb = RAM_D1;
        else
                reg_tft_rgb = reg_tft_rgb;
                /*
                //Perp. TFT scan for next GCLK
                reg_ram_idx <= 1'b1;        //for scan addr;
                reg_ram_we1 <= 1'b1;
               
                //Now Read/Write
                if( reg_eb_busy )
                        begin
                        reg_eb_busy <= 1'b0;
                        if( reg_rw_ram_flg )        //Read;
                                reg_eb_dat = RAM_D1;
                        else
                                reg_eb_dat = reg_eb_dat;
                        end
                end
                */
end

always @ ( posedge GCLK )
begin
//---------EB BUS Oprating--------------------
        reg_eb_wr_q1 <= EB_WR;        reg_eb_wr_q2 <= reg_eb_wr_q1;
        reg_eb_rd_q1 <= EB_RD;        reg_eb_rd_q2 <= reg_eb_rd_q1;
       
        if( !EB_WR & reg_eb_wr_q2 & !EB_CS )        //EB Write
                begin
                        case( EB_A[1:0] )
                        EBCMD_X:
                                begin
                                if( reg_cmd_xyhl==XYHL_STA )
                                        begin
                                        reg_cmd_x[9:8] <= EB_D[1:0];
                                        reg_cmd_xyhl <= XYHL_END;
                                        end
                                else
                                        begin
                                        reg_cmd_x[7:0] <= EB_D[7:0];
                                        reg_cmd_xyhl <= XYHL_STA;
                                        reg_cmd_addr <= reg_cmd_x+reg_cmd_y*10'd800;
                                        end
                                end
                        EBCMD_Y:
                                begin
                                if( reg_cmd_xyhl==XYHL_STA )
                                        begin
                                        reg_cmd_y[9:8] <= EB_D[1:0];
                                        reg_cmd_xyhl <= XYHL_END;
                                        end
                                else
                                        begin
                                        reg_cmd_y[7:0] <= EB_D[7:0];
                                        reg_cmd_xyhl <= XYHL_STA;
                                        reg_cmd_addr <= reg_cmd_x+reg_cmd_y*10'd800;
                                        end
                                end
                        EBCMD_C:
                                begin
                                reg_ram_wdr1 <= EB_D;
                                reg_cmd_xyhl <= XYHL_STA;
                                reg_eb_busy <= 1'b1;
                                reg_rw_ram_flg <= 1'b0;        //write
                                end
                        EBCMD_P:
                                begin
                        //        reg_cmd_x[7:0] <= EB_D[7:0];
                        //        reg_cmd_xyhl <= XYHL_STA;
                        //        reg_next_sm <= 3d'2;
                                reg_rw_ram_flg <= 1'b1;
                        //        reg_cmd_addr <= reg_cmd_x+reg_cmd_y*10'd800;
                                reg_eb_busy <= 1'b1;
                                end
                        endcase
                end
       
        //---------RAM Scan Oprating------------------
        if( TFT_CLK == 1 )
                begin
                //Perp. TFT scan for next GCLK
                reg_ram_idx <= 1'b1;        //for scan addr;
                reg_ram_we1 <= 1'b1;
                end
        else
                begin
                if( TFT_DE == 1 )
                        begin
                        if( reg_scan_addr < 20'd480000 )
                                reg_scan_addr <= reg_scan_addr+1'b1;
                        else
                                reg_scan_addr <= 0;
                        end
                else
                        begin
                        if( reg_scan_addr < 20'd480000 )
                                reg_scan_addr <= reg_scan_addr;
                        else
                                reg_scan_addr <= 0;
                        end
                       
                //--------
                if( reg_eb_busy )
                        begin
                        reg_eb_busy <= 1'b0;
                        if( reg_rw_ram_flg )        //Read;
                                reg_ram_we1 <= 1'b1;
                        else
                                reg_ram_we1 <= 1'b0;
                               
                                reg_ram_idx <= 1'b0;
                                if( reg_cmd_addr < 20'd479999 )
                                        reg_cmd_addr <= reg_cmd_addr+1'b1;
                                else
                                        reg_cmd_addr <= 0;
                        end
                end       
end
endmodule



module TFT_CTRL(
        input  INCLK,
        input  [7:0]RGB,
        output LCDCLK,
        output Hsync,
        output Vsync,
        output DE,
        output R0_3,
        output R1_4,
        output R2_5,
        output G0_3,
        output G1_4,
        output G2_5,
        output B0_2_4,
        output B1_3_5
);

//---------TFT LCD Ctrl-----------
//Ref the NL8060bc31-01 LCD Datasheet
reg thp  = 1'b0;        //assign to TFT_Hsync
reg tvp  = 1'b0;        //assign to TFT_Vsync
reg h_de = 1'b0;        //Hsync de
reg v_de = 1'b0;        //Vsync de
reg [9:0]h_counter = 10'b00_0000_0000;        //1024 max
reg [9:0]v_counter = 10'b00_0000_0000;        //1024 max

reg reg_tft_clk = 1'b0;
always @( posedge INCLK )
        reg_tft_clk <= ~reg_tft_clk;        //TFT CLK

assign  LCDCLK = reg_tft_clk;


//Hsync & Vsync period counter (th&tv)
always @( posedge LCDCLK )
        if( h_counter==10'd1023 )//==th-1
        begin
                h_counter <= 0;
                if( v_counter==10'd624 )//==tv-1
                        v_counter <= 0;
                else
                        v_counter <= v_counter+1'b1;
        end
        else
                h_counter <= h_counter+1'b1;


//Hsync & Vsync & DE line control
assign Hsync = thp;
assign Vsync = tvp;
assign DE = h_de&v_de;

assign R2_5   = RGB[7];
assign R1_4   = RGB[6];
assign R0_3   = RGB[5];

assign G2_5   = RGB[4];
assign G1_4   = RGB[3];
assign G0_3   = RGB[2];

assign B1_3_5 = RGB[1];
assign B0_2_4 = RGB[0];

always @( posedge LCDCLK )
begin
        ///////////////////////////////////////////////////////////////////
        //
        //                Hsync Line Control
        //
        ///////////////////////////////////////////////////////////////////
        //thp period(72)
        if( h_counter<7'd72 )//<thp
                thp <= 0;
        else
                thp <= 1;
        //thb period(128) thd period(800)
        if( h_counter<8'd200 | h_counter>10'd999)        //hc<thp+thb | hc>thp+thb+thd-1
                h_de <= 0;
        else
                h_de <= 1;
       
        ///////////////////////////////////////////////////////////////////
        //
        //                Vsync Line Control
        //
        ///////////////////////////////////////////////////////////////////
        //tvp period(2)
        if( v_counter<3'd2 )//tvp
                tvp <= 0;
        else
                tvp <= 1;
        //tvb period(22)/tvd period(600)
        if( v_counter<5'd24 | v_counter>10'd623)        //vc<tvp+tvb | vc>tvp+tvb+tvd-1
                v_de <= 0;
        else
                v_de <= 1;
end

endmodule

阿莫论坛20周年了!感谢大家的支持与爱护!!

知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)

出0入90汤圆

发表于 2010-8-4 08:21:19 | 显示全部楼层
无图无真相

出0入0汤圆

发表于 2010-8-4 09:27:15 | 显示全部楼层

出0入0汤圆

发表于 2010-8-4 09:46:43 | 显示全部楼层
坛子里这方面的高手不少。

出0入0汤圆

发表于 2010-8-4 10:30:32 | 显示全部楼层
mark

出0入0汤圆

 楼主| 发表于 2010-8-4 14:06:07 | 显示全部楼层
今天调试了一下,基本可以显示图片了。但是时序还要优化!
另外想问问:没有外部复位信号的CPLD如何自己复位?

出0入0汤圆

发表于 2010-8-4 14:28:36 | 显示全部楼层
240宏够吗?我只有100脚的570 IO不够,正在郁闷中

R0,R1,R2, G0,G1,G2, B0,B1 这个是叫多少色?

出0入0汤圆

发表于 2010-8-4 18:26:38 | 显示全部楼层
这个应该上是256色。

出0入0汤圆

 楼主| 发表于 2010-8-5 11:11:29 | 显示全部楼层
240肯定够,我用的就是别人的驱动板,自己没有画板子。也没钱打板子!

以前没有玩过verilog现在手头上有块转接板就自己玩玩练练手,说不定哪天能用上!

256色正解 因为一共才8位嘛!

出0入0汤圆

发表于 2010-8-5 17:27:14 | 显示全部楼层
用哪家的板子哦。。

出0入0汤圆

发表于 2010-8-5 23:03:43 | 显示全部楼层
www.mcutech.cn  256色单片机并行总线控制TFT彩色液晶屏

出0入0汤圆

 楼主| 发表于 2010-8-12 12:21:44 | 显示全部楼层
不知道是哪家的了,很旧的一块板子了,自己用万用表量了下引脚接口然会画了它的原理图,然后对着写程序!
现在已经能完全驱动了,单片机接口也可以操作了写x,y,color方式。只是数据从单片机写快了会有点闪屏(有麻点),
不写数据了又正常显示了,应该不是写数据或从RAM读数据到TFT的问题,因为只要不写数据就不闪屏(也没有麻点了)。

正在思考原因在哪!

出0入0汤圆

发表于 2010-8-12 13:31:36 | 显示全部楼层
思路问题
解决办法,25M数据交替读写,外部写入速度降低到25M

出0入0汤圆

发表于 2010-8-12 13:33:17 | 显示全部楼层
论坛不是有相应代码呀,好几位兄弟发过了

出0入0汤圆

发表于 2010-8-12 13:36:06 | 显示全部楼层
还有下文么?

出0入0汤圆

 楼主| 发表于 2010-8-12 14:53:24 | 显示全部楼层
回复【12楼】again
-----------------------------------------------------------------------
解决办法,25M数据交替读写,外部写入速度降低到25M

应该不是你说的这个问题,应该是Verilog中的逻辑问题,我现在在想办法找出问题的根源!

出0入0汤圆

发表于 2010-8-12 15:56:40 | 显示全部楼层
楼主上原理图啊?

出0入0汤圆

 楼主| 发表于 2010-8-12 16:09:33 | 显示全部楼层
这个板子简单的要死,就一片cpld和2片512k-8bitSRAM,然后外部与单片机的接口。和verilog无关,只是分配引脚的时候看看原理图就好了!

出0入0汤圆

发表于 2010-8-12 16:25:10 | 显示全部楼层
现在进展如何了。

出0入0汤圆

 楼主| 发表于 2010-8-12 17:39:26 | 显示全部楼层
回复【18楼】lvhaian 安哥
-----------------------------------------------------------------------------------
还没进展,读写以及显示都没有问题, 但是当读写数据时屏幕会出现麻子,读写晚后恢复正常,
还在找原因。

出0入0汤圆

 楼主| 发表于 2010-8-14 15:40:23 | 显示全部楼层
郁闷,想了很多办法,依然是偶尔在写数据时,写错地方。

地址同步这个问题很麻烦啊!

出0入0汤圆

发表于 2010-8-14 17:13:46 | 显示全部楼层
回复【12楼】again
思路问题
解决办法,25m数据交替读写,外部写入速度降低到25m
-----------------------------------------------------------------------

我就是这样做的,呵呵!

出0入0汤圆

发表于 2010-8-14 17:42:16 | 显示全部楼层
这个要顶

出0入0汤圆

 楼主| 发表于 2010-8-15 09:18:00 | 显示全部楼层
我的东西都弄好了,支持x,y设置,8bit颜色数据读写!
做完了才发现进步了很多,对于以前不理解的verilog里的东西也理解了很多!
希望以后多交流!

出0入0汤圆

发表于 2010-8-15 09:29:01 | 显示全部楼层
CPLD没写费了吧。。看资料只能刷100次

出0入0汤圆

发表于 2010-8-15 14:51:23 | 显示全部楼层
华瑞纳电子为您提供晶振全系列,各种厂家,封装,频点,质量保证,价格优势,长期现货,零售批发.联系范先生 QQ 659888573 手机13924789528  http://store.taobao.com/shop/view_shop-9b9adcd49a1ea0bfe20910b1181045a6.htm
谢谢.

出0入0汤圆

发表于 2010-8-15 14:52:28 | 显示全部楼层
【23楼】 whwlxl

能分享下么?

出0入0汤圆

 楼主| 发表于 2010-8-15 19:16:32 | 显示全部楼层
回复【21楼】tly823875
-----------------------------------------------------------------------

哎,调试发现还是有偶尔有麻点出现,可能还是地址同步的问题,想了很多办法了。
我看了你的是18位地址总线,不需要计算地址,容易很多!我的是要先写2次8bit x, 2次8bit y,
然后自己计算地址。这个地方很容易出现问题。

出0入0汤圆

发表于 2010-8-16 09:38:21 | 显示全部楼层
回复【27楼】whwlxl
回复【21楼】tly823875  
-----------------------------------------------------------------------
哎,调试发现还是有偶尔有麻点出现,可能还是地址同步的问题,想了很多办法了。
我看了你的是18位地址总线,不需要计算地址,容易很多!我的是要先写2次8bit x, 2次8bit y,
然后自己计算地址。这个地方很容易出现问题。
-----------------------------------------------------------------------
你走到我前面了,我还没有计算地址呢,我是实现了一个字节对应8个点而已。
你说的嘛点问题,我遇到过,我的解决方法是改变读写sram的位置,后来就没有了
另外还要注意:数据的延时问题,估计1~2个clk
显示图像要画出边框,才能准确的看到位置是否完全正确,分辨率太高,点细,放大镜也看不清楚,呵呵

出0入0汤圆

 楼主| 发表于 2010-8-16 12:41:01 | 显示全部楼层
回复【28楼】tly823875
-----------------------------------------------------------------------
谢谢你的支持,关于像素对齐现在是没问题的,我放一副图片,边框用不同颜色来显示。就知道显示与写数据是否有偏移了。
地址计算涉及到乘法,延时严重。我的数据麻点只是出现在连续设置x,y地址然后写颜色时出现麻点。如果是写数据地址自动
+1模式不会出现麻点,不写数据更不会。分析下来主要是地址计算后的写入问题,这个同步关系要搞好。你可以试着这样做,
会麻烦很多的。特别是时序上的安排!因为我的数据线8位,地址线2位,

写入方式 A1~A0
   00: x 低, x 高;(写入完整后计算RAM地址)
   01: y 低, y 高;(写入完整后计算RAM地址)
   02: 颜色数据  地址自动加1

读方式 A1~A0
   02: 颜色数据  地址自动加1


郁闷啊!麻点(偶尔出现在连续设置x,y后写颜色数据到ram)这个难题真难解决。
我目前也是25兆的速度在搞,时钟0: 先读数据到TFT,然后地址增加1;时钟1:读/写 RAM数据如此交替。

出0入0汤圆

发表于 2010-8-16 15:56:29 | 显示全部楼层
这个要顶,继续观察

出0入0汤圆

发表于 2010-8-16 19:13:33 | 显示全部楼层
能不能把最新的程序公布下啊,想学习啊

出0入0汤圆

发表于 2010-8-17 21:49:14 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-8-17 22:55:07 | 显示全部楼层
关注

出0入0汤圆

发表于 2010-8-17 23:46:58 | 显示全部楼层

(原文件名:04.jpg)

出0入0汤圆

发表于 2010-8-18 09:12:44 | 显示全部楼层
做个记号

出0入0汤圆

发表于 2010-9-27 19:47:31 | 显示全部楼层
MARK

出0入0汤圆

 楼主| 发表于 2010-10-23 11:18:19 | 显示全部楼层
问了下一些坛子的牛人,据说是要搞时序约束,不知道有没有这方面的资料和建议

出0入0汤圆

发表于 2014-5-8 19:50:07 | 显示全部楼层
逻辑设计是最重要的,不一定要做时序约束,只要能保证数据能正确写入和读出就没问题了。
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-7-24 03:19

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表