西洲渡

一只还没迈入IC领域的小菜鸡

LCD1602驱动模块设计

LCD驱动模块前端设计流程

需求分析

  1. 使用Verilog代码完成LCD1602型号的液晶显示屏驱动设计
  • LCD驱动模块的上位机为主控系统,下位机为LCD1602液晶显示屏;
  • 要求LCD驱动模块与主控系统交互时使用APB接口(APB时钟采用64MHz) ;
  • 该驱动模块工作时钟使用外部时钟(工作时钟采用50MHz) ;
  • 该模块初始化完成后,它所驱动的LCD1602液晶显示屏默认输出“ABCD至MNOP abcd至mnop”共16*2个英文字符,主控系统可通过APB总线控制液晶显示屏输出的字符;
  • 该模块内部需要设计使能寄存器,模块每次向LCD1602液晶显示屏输出新的字符时,均需要通过APB总线配置使能寄存器;
  • 该模块内部需要设计BUSY寄存器,主控系统可以通过APB总线读取驱动模块的忙或不忙状态(16*2个字符正在向显示屏输出,则模块处于忙状态,否则处于不忙状态)﹔
  • 本设计只向LCD液晶显示屏写入数据,不对其进行读操作。
  1. 字符型的显示原理
  • 用LCD显示一个字符时比较复杂,因为一个字符由6×8或8×8点阵组成,既要找到和显示屏幕上某几个位置对应的显示RAM区的8字节,还要使每字节的不同位为”1”,其它的为”0”,为”1”的点亮,为”0”的不亮。这样一来就组成某个字符。
  • 内带字符发生器的控制器来说,显示字符就比较简单了,可以让控制器工作在文本方式,根据在LCD上开始显示的行列号及每行的列数找出显示RAM对应的地址,设立光标,在此送上该字符对应的代码即可。
  1. RAM形式的标准字库

液晶显示模块是一个慢显示器件,所以在执行每条指令之前一定要确认模块的忙标志为低电平,表示不忙,否则此指令失效(通过LCD读时序发送指令9)。要显示字符时要先输入显示字符地址,也就是告诉模块在哪里显示字符,如图是1602的内部显示地址

功能架构

LCD驱动模块的上位机为主控系统,下位机为LCD1602液晶显示屏

功能划分

硬件实现

该模块初始化完成后,它所驱动的LCD1602液晶显示屏默认输出“ABCD至MNOP abcd至mnop”共16*2个英文字符,主控系统可通过APB总线控制液晶显示屏输出的字符;

软件实现

  1. 该模块内部需要设计使能寄存器,模块每次向LCD1602液晶显示屏输出新的字符时,均需要通过APB总线配置使能寄存器;
  2. 该模块内部需要设计BUSY寄存器,主控系统可以通过APB总线读取驱动模块的忙或不忙状态(16*2个字符正在向显示屏输出,则模块处于忙状态,否则处于不忙状态);

接口协议

LCD1602液晶模块内部的控制器共有11条控制指令,如下表所示:

序号 指令 RS R/W D7 D6 D5 D4 D3 D2 D1 D0
1 清显示 0 0 0 0 0 0 0 0 0 1
2 光标返回 0 0 0 0 0 0 0 0 1 *
3 置输入模式 0 0 0 0 0 0 0 1 I/D S
4 显示开/关控制 0 0 0 0 0 0 1 D C B
5 光标或字符移位 0 0 0 0 0 1 S/C R/L * *
6 置功能 0 0 0 0 1 DL N F * *
7 置字符发生存储器地址 0 0 0 1 字符发生存储器地址
8 置数据存储器地址 0 0 1 显示数据存储器地址
9 读忙标志或地址 0 1 BF 计数器地址
10 写数到CGRAM或DDRAM 1 0 要写的数据内容
11 从CGRAM或DDRAM读数 1 1 读出的数据内容

指令1:清显示,指令码01H,光标复位到地址00H位置。
指令2:光标复位,光标返回到地址00H。
指令3:光标和显示模式设置VD:光标移动方向,高电平右移,低电平左移S:屏幕所有文字是否左移或者右移。高电平表示有效,低电平则无效。
指令4:显示开关控制。D:控制整体显示的开与关,高电平表示开显示,低电平表示关显示C:控制光标的开与关,高电平表示有光标,低电平表示无光标B:控制光标是否闪烁,高电平闪烁,低电平不闪烁。
指令5:光标或显示移位S/C:高电平时移动显示的文字,低电平时移动光标。
指令6:功能设置命令DL;高电平时为4位总线,低电平时为8位总线N;低电平时为单行显示,高电平时双行显示F:低电平时显示57的点阵字符,高电平时显示510的点阵字符。
指令7:字符发生器RAM地址设置。
指令8:DDRAM地址设置。
指令9:读忙信号和光标地址BF:为忙标志位,高电平表示忙,此时模块不能接收命令或者数据,如果为低电平表示不忙。
指令10:写数据。
指令11:读数据。

接口时序

APB写时序

如图所示,地址(PADDR)、写信号(PWRITE)、选择信号(PSEL)、写数据(PWDATA)在时钟上升沿到来时有效。表明一次写传输的开始,传输的第一个时钟周期称为SETUP周期。在第二个时钟上升沿使能信号(PENABLE)有效,进入ENABLE周期。而地址、写数据和控制信号需要在此期间保持有效。传输在ENABLE周期结束时完成,此时PENABLE变为低电平,PSEL也变为低电平。

APB读时序

由图所示,地址(PADDR)、写信号(PWRITE)、选择信号(PSEL)、写数据(PWDATA)在时钟上升沿到来时有效。在读传输时,从设备必须在ENABLE周期提供数据,读数据在ENABLE周期结束的时钟上升沿被主设备采样。

LCD写操作时序

如图所示,在LCD写操作时序中,RS引脚和R/W引脚先变化,其中R/W引脚先置高,变化了tAS时间后使能引脚E从低电平变为高电平,然后上位机写入DB数据,写完之后,使能信号E从高变低。

Item Symbol Min Typ Max Unit
Enable cycle time tcycE 500 - - ns
Enable pulse width(high level) PWEH 230 - - ns
Enable rise/fall time tEr,tEf - - 20 ns
Address set-up time(RS,R/W to E) tAS 40 - - ns
Address hold time tAH 10 - - ns
Data set-up time tDSW 80 - - ns
Data hold time tH 10 - - ns

LCD读操作时序

如图所示,RS和R/W引脚先变化,因为是读操作R/W引脚首先置为高电平经过tAS时间后,使能引脚E才从低电平变到高电平,经过tD时间后,我们进行数据读取,读取完成后,再把使能E拉低,经过一段时间后,可以继续下一次读写操作。

图6 LCD读操作时序

Item Symbol Min Typ Max Unit
Enable cycle time tcycE 500 - - ns
Enable pulse width(high level) PWEH 230 - - ns
Enable rise/fall time tEr,tEf - - 20 ns
Address set-up time(RS,R/W to E) tAS 40 - - ns
Address hold time tAH 10 - - ns
Data delay time tDDR - - 100 ns
Data hold time tDHR 5 - - ns

功能分解

结构框架

  • 设计框架主要由APB、LCD接口,内部寄存器模块,LCD主状态机控制模块构成
  • 数据或命令内部寄存使用多组寄存器来设计,每组寄存器对应4个字符,一个字符8bit数据
  • LCD主状态机控制可灵活设计,包括打开功能设置、关闭显示、清显示、设置为输入模式、打开显示、光标跳至1行1列、光标跳至2行1列命令以及显示数据等状态,要满足驱动模块通过控制HD44780芯片,来实现LCD显示的目的
  • LCD驱动模块的复位通过外部复位信号控制
  • LCD时序只需要设计写操作即可

APB接口和LCD接口

  • APB接口模块要设计为从机接口,时钟采用64MHz,地址数据位宽均为32bit,此接口可以使用ready,也可以不使用。
  • LCD接口模块要设计为主机接口,时钟采用50MHz,data7-0值包含数据和命令。
    读状态 输入 RS=L,R/W=H,E=H 输出 D0-D7=状态字
    写指令 输入 RS=L,R/W=L,D0-D7=指令码,E=高脉冲 输出
    读数据 输入 RS=H,R/W=H,E=H 输出 D7-D0=数据
    写数据 输入 RS=H,R/W=L,D0-D7=数据,E=高脉冲 输出

寄存器功能

  • 字符显示寄存器:主控系统通过APB总线对LCD驱动模块的寄存器进行读写,将字符对应的十六进制码(可通过工具生成)写入字符寄存器
  • 使能寄存器:写入字符寄存器后,打开使能控制寄存器,LCD驱动对LCD1602液晶显示屏进行写字符操作
  • BUSY寄存器:主控系统对整个驱动流程可通过APB总线来查询驱动模块是否处于忙状态

初始化(复位)过程

  • 在LCD驱动初始化功能

    驱动上电完成后延时15ms
    写指令38H(不检测忙信号)
    延时5ms
    写指令38H(不检测忙信号)
    延时5ms
    写指令38H(不检测忙信号)
    以后每次写指令、读/写数据操作均需要检测忙信号(以下指令在每帧的LCD字符重新输出时,都要执行)
    写指令38H:显示模式设置
    写指令08H:显示关闭
    写指令01H:显示清屏
    写指令06H:显示光标移动设置
    写指令0CH:显示开及光标设置

  • LCD驱动初始化完成驱动LCD液晶显示屏显示“ABCD至MNOP abcd至mnop”共16*2个英文字符

主状态机功能

  • 主状态机主要实现向LCD1602内置的HD44780芯片发送命令,用于控制屏幕显示、关闭,控制光标的位置与移动字符显示。
  • 在字符显示状态时,首先要输出显示地址,即光标的位置,之后输出要显示字符的十六进制数据,此时LCD1602的光标会自动后移。
  • 在光标移动到每一行的最后位置时,需要通过命令调正光标回到下一行的首列。

功能设计

时钟、复位

模块中使用一个外部50MHz工作时钟和64MHz的APB时钟,复位使用外部复位,低电平复位有效,高电平释放复位,采用异步复位同步释放。

字符写入过程

  • 写入显示地址时要求最高位D7恒定为高电平1,例如第二行第一个字符的地址是40H,实际写入的数据应该是01000000B (40H) +10000000B(80H) = 11000000B(C0H)。
  • 在液晶模块显示字符时光标是自动右移的,无需人工干预。
  • 1602液晶模块内部的字符发生存储器(CGROM)已经存储了160个不同的点阵字符图形,这些字符有:阿拉伯数字、英文字母的大小写、常用的符号、和日文假名等,每一个字符都有一个固定的代码,比如大写的英文字母“A”的代码是01000001B(41H),显示时模块把地址41H中的点阵字符图形显示出来,我们就能看到字母“A”。

主状态机

  • 状态共分为打开功能设置(发送38H)、关闭显示(发送08H)、清显示(发送01H)、设置为输入模式(发送06H)、打开显示(发送OCH)、光标跳至1行1列(发送80H)、发送字符(发送数据)、光标跳至2行1列(发送COH)、发送字符(发送数据)命令。
  • 输出只和状态有关而与输入无关,故采用Moore状态机。

image.png

显示流程

image.png

功能仿真

  1. 将写好的rtl代码使用make命令运行,其中Makefile文件中包含

  1. 打开图形界面后,选中顶层点击Dump,然后进行仿真,并查看run.log。




  1. 将顶层文件中的端口添加到波形窗口查看波形。


从上图我们可以看出LCD驱动模块初始化之后,会先对液晶显示屏输入命令做初始化设置,再驱动LCD液晶显示屏显示“ABCD至MNOP abcd至mnop”共16*2个英文字符。

上图为APB接口波形图,此时上位机通过APB接口先配置显示使能寄存器,再配置字符寄存器。

上图为上位机配置内部寄存器以后,LCD驱动模块驱动下位机重新显示字符的波形图,从波形图上来看,配置寄存器以后驱动模块依然能正常向下位机LCD1602液晶显示屏发送数据,符合功能设计需求。

LCD驱动模块后端流程

逻辑综合

逻辑综合将 RTL 编码转换为特定时序约束下的门级网表和约束,具体操作使用DC软件完成。

  1. 在工作空间target中建立目录树

  1. 创建.synopsys_dc.setup文件,此文件在启动DC初始化环境的时候自动调用,该文件配置库文件的搜索路径,指定target library和link library的工艺库文件。其中target library中包含了cell的库文件以生成网表,link library中包含了设计网表中的cell。

  1. 启动DC
  • 在work目录中启动dc_shell
  • 使用source ../analyze_source_file.tcl读入需要综合的RTL代码文件

  • 使用elaborate lcd1602声明顶层模块

  • 使用link查看是否缺少子模块,返回值为1则说明文件完整

  1. 设计约束文件
  • 在clock部分我们创建端口时钟和一个虚拟时钟,设置周期和占空比以及建立保持时间。
  • 在con部分我们给所有的输入输出端口(除时钟外)设置输入输出延时。
  • 在DRC部分我们给当前设计设置了最大转换时间和最大扇出,始终设置最大转换时间
  • 在timing部分我们给输入输出端口设置建立保持时间约束。

  1. 编译并输出
  • 使用compile命令对当前的设计进行逻辑综合

  • 编译完成后我们需要输出后面的时序约束文件和网表文件,使用change_names -hierarchy -rules verilog更改变量名使之符合Verilog语法规则。
  • 使用write -format verilog -hierarchy -output ../output/lcd1602.v命令输出网表文件
  • 使用write_sdc ../output/lcd1602.sdc输出时序约束文件

布局布线

布局布线将区域内的cell安置在相应的位置并用金属层进行连接,具体操作利用ICC完成。

  1. 配置ICC环境并启动
  • 首先我们在target工作目录中新建PR文件夹,在PR文件夹中同样需要.sysnopsy_dc.setup配置文件,内容和SYM中的一致。
  • 使用icc_shell启动ICC。
  • 使用create_mw_lib XXX(设计库名称) -open -technology XXX(工艺库路径+名称) - mw_reference_library XXX(参考库路径+名称)命令创建milkway设计库
  • 使用read_verilog ../SYM/output/lcd1602.v读入综合生成的网表文件。
  • 使用link命令将网表中的的单元和参考库中的单元连接起来,然后使用check_design。
  • 使用read_sdc ../SYM/output/lcd1602.sdc读入综合生成的约束文件。
  • 使用check_timing检查约束文件是否导入。
  • 使用set_tlu_plus_files -max_tluplus XXX(路径+max.tluplus) -min_tluplus XXX(路径+min.tluplus) -tech2itf_map XXX(路径+tluplus.map)命令导入寄生参数文件,然后使用check_tlu_plus_file检查tlu文件是否导入。
  1. 打开图形界面并进行布局布线
  • 使用start_gui命令打开ICC的图形界面,然后再工具栏点击creat floorplan创建平面图。

  • 选择工具栏Preroute中Create Power Straps在进行引脚和网络的连接。

  • 选择工具栏Preroute中Create Power Straps在图形界面中画出六、五、四层金属电源线(VDD和VSS)。


  • 选择工具栏Preroute中Preoute standard cells中的fill empty rows,填充空行,并在DRC中布置M1-M4的power rail。

  • 选择工具栏中Floorplan中的create placement blockage工具,遮住标准单元的第一行和最后一行,然后选择工具栏Finishing中的add tap cell array将标准单元N阱和衬底接电源和地,防止闩锁效应。

  • 在终端使用check_physical_design -stage pre_place_opt和check_physical_constraints命令检查设计和约束。
  • 在终端里使用place_opt命令进行自动布局,使用report_qor评估布局质量。

  • 使用set_propagated_clock [all_clocks]命令进行设置时钟,使用clock_opt命令进行时钟树综合。

  • 使用route_opt进行自动布线。

  1. 时序检查、DRC检查和违例修正
  • 使用reqort_qor查看时序报告,检查建立/保持时间的违例。使用verify_drc做DRC检查。
  • 使用report_timing -transition_time检查建立/保持时间的违例。
  • 使用size_cell u_apbif/U355 AND3_X2M_A7TULL命令修改对应建立时间违例。

  • 如果有保持时间违例,可以使用insert_buffer添加到路径中,直到时序正常。
  • 使用legalize_placement -incremental和route_zrt_eco命令重新进行布局布线。
  • 使用verify_zrt_route进行DRC检查。

  • 检查没有任何违例之后使用save_design命令保存设计并退出。