CrazyBingo

【最苦逼电工】FPGA+ARM=1080P LCD记录一次开发历程-YouKU视频

1
阅读(18744) 评论(51)

大家写NB或者苦逼,都是总结过去的为吧,呵呵我完整地实时记录一下我这次 FPGA+ARM=LCD显示控制器的开发的开发历程。当然最初的梦想应该追溯到2012年8月份了,当年采用Cyclone IV FPGA,以及STM32实现了,发挥了Cyclone IV强大的可编程锁相环,实现了动态时钟分配,完成了“任意分辨率的通用LCD控制器”,给个图记录一下当年的辉煌,如下:



/********************************华丽的分割线************************************/

coco姐姐说“视频图像处理”小组要活起来,最近刚好又重新弄LCD,那就准备火起来一下。、、、、


在“视频图像处理”小组我发布了《[原创]  《提问的智慧》-同时希望我们小组重振雄风http://group.chinaaet.com/116/78195,希望能有更多的人去提问,只要我能回答的,我会给出详细的答案,仅此希望有更多志同道合的朋友走到一起!!!

/********************************华丽的分割线************************************/



由于LCD显示器速度快,数据量大,时序要求高,用传统的单片机实现高分辨率的LCD显示器驱动,在带宽上有着很大的瓶颈,在功能上明显的不足。本系统采用Cyclone IV FPGA,以独特的架构,以及全新的设计模式,实现极具性价比的“通用显示控制器”—“Universal LCD Controller”,此处简称“ULC”。


本系统旨在实现兼容各种分辨率的LCD显示控制器,可用于LCD显示器视频图像显示,主要功能如下所示:

① Intel 8080接口ULC参数配置及数据传输

② SDRAM图像数据高速缓存

③ 任意分辨率的LCD显示器驱动

④ 实现了1024*768@60Hz分辨率为上限的显示控制器

作为ULC,本系统可通过外部处理器,比如ARMMCU)配置寄存器,异步实现低速时钟域向高速时钟域传输数据,实现高速显示器的显示驱动,突破传统单片机带宽低的瓶颈。

本系统已成功实现ARM7800*480@60Hz LCD方案,以及ARM71024*768@60Hz VESA显示方案,结果经过多次验证,以及长时间的测试,在功能上实现要求,在画面上比较流畅,在性能上相对稳定,从根本上实现了任意分辨率LCD显示控制器的各项指标,完成了从单片机到高速LCD的跨时钟域数据切换,以及显示驱动。

当年是给某LCD厂家定制的LCD测试版,卡如下所示:



采用Intel8080总线接口,由于协议的简单,同时更方便的移植STM32的FSMC接口,给当时的开发带来了很大的便利,以下简单的介绍一下Intel 8080总线协议:

在片间数据传输中,协议的种类比较多,但Intel 8080接以其使用简单,速度快,应用广泛等诸多优点,多用于LCD液晶显示器配置芯片。如下图所示,Intel 8080总线接口时序。


由于本系统不存在数据的读取,因此系统中无需nRD信号,主机默认为写数据状态。本系统参照8080接口协议,模拟ILI9325 LCD驱动芯片,通过灵活的Verilog HDL,设计了8080接口总线的寄存器配置,和业界达到了类似的标准;同时作为数据传输通道,解决了MCU带宽限制的不足。

相关信号线以及功能如下表所示:

序号

端口

方向

宽度

主要功能

1

MCU_CS#

输入

1

数据输出片选使能信号(L

2

MCU_RS

输入

1

数据(H/命令(L

3

MCU_WE

输入

1

数据写入使能信号(H

4

MCU_DATA

输入

16

16位数据总线



同时,通过8080接口,完整的模拟TFT控制器的操作模式,即通过寄存器等的配置,完成不同LCD,不同模式的驱动实现。简单的给出一个当年定制的地址、寄存器的分配表格,如下所示:


这样,就完成了8080接口--FPGA--LCD控制器之间的定制。。可以任意的在不同分辨率,相同接口(接口可更变、升级)的LCD之间进行开发移植、升级等。当然一个纠结的问题是:不同的LCD可能时钟频率不一样,这需要在线配置时钟。

我请教过一些人,他们使用分频来实现的,但是由于分频不能灵活的实现50%的占空比,而且开发上不是那么的方便,同时门控时钟作为全局时钟使用时,会极大的降低系统的稳定性和可靠性,因不能这样做你们怎么做的??

不过后来Altera推出的Cyclone III/IV NB的可编程锁相环,已经完败了这些方案。。。最低级别的144IO的FPGA有2个PLL,一个PLL所谓系统时钟,另一个PLL作为LCD的驱动时钟,通过系统时钟控制驱动时钟的改变,完美的实现了可编程锁相环方案的任意LCD控制器。最简单的动态锁相环altpll_reconfig可以用mif来实现配置,如下图所示:

详细的说明可以研究Altera Implementing PLL Reconfiguration in Cyclone III Devices》手册,总之这是一个好东西啊。。。。



接下是LCD控制器的缓存,这是一个痛苦的问题、、、、CB当年使用的是HY57V641620 16Bit宽度的SDRAM。。。虽说也看过无数个SDRAM的手册,对SDRAM的操作也算是一知半解,但是一直懒得写,因为一直有大神笼罩着,移植了特权的代码,做了一些修改、升级,弄出了一个半成品。。。特某人关于SDRAM开发的博客如下所示,这是他当年的记录,貌似3年过去了。。。time is flying。。。

http://bbs.ednchina.com/BLOG_ARTICLE_229827.HTM


特权的SDRAM实现了对SDRAM BANK的突发读写,但是没有实现内部乒乓机制,为了实现完整的片内乒乓操作,Bingo花9牛二虎之力,实现了SDRAM内部Bank的乒乓,完成了图像的完整搬迁。关于“不完整乒乓操作法”,Bingo设计了如下框图,通过高频去实现低频域的乒乓,相信你应该看得懂:


废话少说,框图如下(此图由于某些原因,不能给完整清晰的,抱歉):


接下来啊是LCD控制器。。。。。关于LCD控制器,BIngo从09年玩到现在,09,10,11,12,13,14,计算数字貌似6年了,实在是太快了。。

关于LCD/VGA的开发,CB当年也是轰轰烈烈的做过一番“事业”的,从1602,5110,12864,到TFT,QVGA,MIPI(正在弄),对此有足够的经验,也算是玩过一阵子。想当年(只是想当年)最满意的是,就是搞定了1024*768真彩美女的显示,网址如下:

http://www.cnblogs.com/crazybingo/archive/2010/12/09/1900816.html

http://www.amobbs.com/forum.php?mod=viewthread&tid=4437397(小心,这里有代码)

时间是2010年12曰9日,那时候CB还在大三呢。。。不过现在的大三太可怕了,长江后浪推前浪,前浪死在沙滩上。。。。。。当年这个方案是通过Nios-SRAM-VGA实现的。尽管没有什么使用价值,但却对当时的自己有巨大的自信心。呵呵 闹着玩。。


由于篇幅有限,另外在给出关于CB当年总结的VGA开发文档,如下:

第十四章 没我不行——基于FPGA的VGA可移植模块终极设计

http://blog.chinaaet.com/detail/21606.html

第十五章 终于有了——基于FPGA的C2Mif软件设计以及VGA应用


http://blog.chinaaet.com/detail/21782.html




*************开始华丽的升级*************



因此,就目前而言,万事俱备,最终的框架如下,应该是这样子的:


最终实现的就是本篇博客发的第一个图。。。


但是完美是没有极限的,由于HY57V641620只能支持16Bit,因此24Bit的LCD不能实现完整的驱动,只能做个阉割版的、。。。为此,最终由于需求,需要升级为24Bit,甚至32Bit的SDRAM。相关SDRAM的物理对比,如下所示:


当然选用了MT48LC8M32这个32Bit的SDRAM,来作为升级版本的LCD控制器缓存。。在开发商除了升级SDRAM控制器,还需要升级8080总线接口,需要把16Bit升级到32Bit总线。。。或者32Bit分2次写入数据,实现完整的16Bit数据。。。。32Bit写入比较方便,但是位宽、、、第二种比较麻烦,但是带宽。。。。。


权衡,暂时用16Bit写入,通过扩展是实现24Bit去实现方案的第一步,慢慢升级。。。目前做到了这一步,如下所示。目前还在FPGA端模拟写入、仿真阶段。ARM慢慢来。。目前LCD分辨率为800*480.。

不过发现了很多问题,比如直接用LCD模拟边框写入,来测试数据是否一个都不丢,是OK的如下:


但是通过SDRAM--LCD就成了这样了。(注意,右边那一列少了。。。)


分析整个数据通道,有三个可能出现问题的地方:

(1)写入DCFIFO时,是否丢失数据

(2)从DCFIFO写入SDRAM是否丢失数据

(3)从SDRAM写入到DCFIFO时是否丢失数据

(4)从DCFIFO到LCD控制器时是否丢失数据

(5)LCD控制器是否时序不完美,丢失数据(这个前面已经确认OK了)

这一步真的好特么的痛苦,不停地用Signal Tap II。。。。。今天只能先到这里,步步为营,一步一个脚印,实时的给大家补充、更新我的调试结果,也告诉大家难点、问题的出处,更重要的是如何解决问题的一个方案!!!!


(5)能确认没问题。。。

测试的屏幕模拟写入0-799这800个数据,数据刚测试了一下(4)输出的数据是这个样子的:



可见输入前端是OK的,即从0开始,但是最后,798重复了一次,却没有799.。。。这个799哪里去了呢????




2014年1曰3日 23:19分,搞定:如下图所示

简单的说,我们可以确定最快确定以下2个方面:

(1)外部数据写入DCFIFO,这个是受我们控制的

(2)数据从DCFIFO读出到LCD控制器,这个实收我们控制的。。

但是不确定的是,所以移植的SDRAM控制器,对于WR-DCFIFO的读取,与对RD-DCFIFO的写入部分的时序。。。实际通过Signaltal II来进行数据的抓包,最后发现数据写入滞后了一个时钟,因此将WR-DCFIFO设置为数据提前到数据口,竟然问题解决,该设置如下所示:


给出最后DCFIFO到LCD控制器的时序吗,如下所示:



完美解决问题!!!哈哈




2014年1曰4日 16:27:

话说昨天以为完美,但实际上并不完美。。。我发现了一个自认为不应该出问题的问题,即将DCFIFO的输出端设置为数据提前到达端口,进入Terasic的SDRAM控制器,数据就会256为周期的出现一个数据的错误。。。。。没辙了 如果不这样做。。。又不能实现的完整的帧。。

测试发现持续写入的时候没有问题。。而离散写入,即通过wr使能信号,离散的写入数据就会出错。。。为了解决数据不连续,同时保证进入SDRAM控制器数据完整的连续的功能,蛋疼的额在外部有添加了一个DCFIFO,实现MCU到控制器的低速→高速数据的归纳综合,离散到连续的突发发送。。。。先给个仿真的图,如下,一看就会懂:(这是离散写入16个数据,突发写入64个数据的低速→高速的优化)


这样一来,数据有连续了。。。。。。。。。。当然由于时间原因,没空研究控制器内部。。只能通过外部的配合,来完成数据的升级。。。。


2014年1曰5日9:28,新的一天又开始了

其实问题并不是前面所说的那样的,真正的问题是由于写入RD-FIFO的时间比SDRAM读取出来要晚了一个时钟。。。Terasic的SDRAM控制器中将DQ读取出来后用REF_CLK打了一拍,变成了mDATAIN,所以数据延迟了一个时钟。。。。我在SignalTapII测试时发现这个问题,花了九牛二虎之力,竟然认为的将写入使能信号滞后1个时钟不行,最后直接将DQ给RD-FIFO写入端,问题解决。

大家移植Terasic的SDRAM控制器的时候,记得这样改一下:


简单的录制了一下最后优化的效果视频,youku网址如下

http://v.youku.com/v_show/id_XNjU3NDc0NzU2.html



2014年1曰7日,经过了各种优化,终于全部移植到ARM上去了,目前实现了800*480LCD的测试,功能如下:

(1)可编程像素时钟

(2)可编程LCD时序参数

(3)可编程SDRAM控制器

(4)暂时支持全帧图像写入。。

上传YOUKU视频,如下所示:





下一步,开始弄MIPI LCD、、、、暂时540*960


2014年1曰7日23:00分

搞定,给个帅气的图,亮瞎你的狗眼!!


下一步,MIPI LCD ,1080P!!!!!!!


2104年1曰7日23:39分,1080P搞定,有图有真相如下:


下一步优化SDRAM地址可编程!!完美是没有极限的!!!


1080P LCD控制器已优化完毕,上传视频呵呵,如下:


睡觉去!!!


2014年1曰9日14:32

我发誓这是最后一个视频,960*540分辨率LCD的双屏同步测试,呵呵,Sharp your eyes


未完待续,为自己加油!!!



  1. 您好,我对您这个LCD驱动方案很感兴趣,希望与您交流。QQ:410107291

  2. @xgj0817   

    牛人,想学怎么办呢?420128237@QQ.COM

    Bingo哥在俺们ChinaAET有个助学小组,会有很多资料包和例程,欢迎到小组学习提问。http://group.chinaaet.com/334/

  3. 牛人,想学怎么办呢?420128237@QQ.COM

  4. 你好,想和你交流下LCD控制问题,13861781282,微信号 谢谢!

  5. CB,能给一份基于SDRAM的乒乓操作的代码来参考一下吗?真的想了很久都没有头绪。1069217225@qq.com
  6. CB,能给一份基于SDRAM的乒乓操作的代码来参考一下吗?真的想了很久都没有头绪。1069217225@qq.com
  7. 引用:MamBa24
    引用:CrazyBingo
    @MamBa24

    FPGA模拟8080总线数据接受。。。然后ARM给数据 就可以了

    还有一点就是,我想问一下CB,我现在也在做SDRAM给FPGA送图像数据,那个兵乓操作具体思路我还是能明白的,但到了实际的写代码,就觉得无从下手,你可以方便解释一下吗?可以发给我的邮箱1069217225@qq.com



    Bingo,就在这统一解释吧!
  8. 引用:CrazyBingo
    @MamBa24

    FPGA模拟8080总线数据接受。。。然后ARM给数据 就可以了

    还有一点就是,我想问一下CB,我现在也在做SDRAM给FPGA送图像数据,那个兵乓操作具体思路我还是能明白的,但到了实际的写代码,就觉得无从下手,你可以方便解释一下吗?可以发给我的邮箱1069217225@qq.com


  9. @MamBa24

    FPGA模拟8080总线数据接受。。。然后ARM给数据 就可以了


  10. CB,我没有学过ARM,你那个ARM模块是不是用STM32+FLASH将图片用I8080总线传输到FPGA的SDRAM里面去?我们搞FPGA的就是用JTAG烧写代码进去,你那个ARM模块不知道是神马的一个操作方式给FPGA送数据?能给我说一下吗?
  11. @myapplewen

    我也是Cyclone IV+STM32啊。。。

    1920*1080 你现在要达到多高的帧率啊

    输入多少fps  输出fps???

    我现在SDRAM啊。。。做到了130M。。。。60fps多点


  12. 最近在开发一款Cyclone 4+STM32的测试平台,主要用作FHD(1920*1280)以下分辨率的显示。最头疼的是DDR2和整个系统的配合。CB有没有好的建议。。
  13. @heijin_fpga
    黑金???你不可能是小马吧????
  14. 顶一个,我顶顶顶顶顶顶顶顶顶顶顶顶顶顶顶顶顶顶顶!

  15. @xiaohe
    哈哈,持续更新 暂告断落  你看看