集成电路技术分享

 找回密码
 我要注册

QQ登录

只需一步,快速开始

搜索
查看: 2666|回复: 2

求lcd1602屏FPGA控制的数字电子钟的verilog例子

[复制链接]
vvt 发表于 2010-6-22 10:47:57 | 显示全部楼层 |阅读模式
求lcd1602屏FPGA控制的数字电子钟的verilog例子
gllby 发表于 2010-6-24 10:55:36 | 显示全部楼层
回复 1# vvt


    这里是一个用Verilog HDL编写是LCD1602例子
module lcd(clk,rst,lcd_e,lcd_rw,lcd_rs,data);
        input clk,rst;
        output lcd_e,lcd_rw,lcd_rs;
        output [7:0] data;
        reg lcd_e,lcd_rw,lcd_rs;
        reg [7:0] datain;
        reg [7:0] data;
       
        reg [10:0] state;
        reg flag;
        reg [5:0] address;
        reg [6:0] counter;
        reg [3:0] divcounter;
       
       
        parameter IDLE                =11'b00000000000;
        parameter CLEAR                =11'b00000000001;                //清屏
       
        parameter RETURNCURSOR        =11'b00000000010;        //归home位
       
        parameter SETMODE        =11'b00000000100;               
        //输入方式设置,读写数据后ram地址增/减1;画面动/不动
       
        parameter SWITCHMODE        =11'b00000001000;       
        //显示状态设置,显示开/关;光标开/关;闪烁开/关
       
        parameter SHIFT                =11'b00000010000;               
        //光标画面滚动 画面/光标平移一位;左/右平移一位
       
        parameter SETFUNCTION        =11'b00000100000;       
        //工作方式设置 1:8/1:4位数据接口;两行/一行显示;5x10/5x7点阵
       
        parameter SETCGRAM        =11'b00001000000;                //设置CGRAM
        parameter SETDDRAM1        =11'b00010000000;                //设置DDRAM
        parameter SETDDRAM2        =11'b00011000000;                //设置DDRAM
        parameter READFLAG        =11'b00100000000;                //
        parameter WRITERAM        =11'b01000000000;                //写RAM
        parameter READRAM        =11'b10000000000;                //读RAM

        parameter cur_inc              =1;
        parameter cur_dec              =0;
        parameter cur_shift            =1;
        parameter cur_noshift          =0;
        parameter open_display         =1;
        parameter open_cur             =0;
        parameter blank_cur            =0;
        parameter shift_display        =1;
        parameter shift_cur            =0;
        parameter right_shift          =1;
        parameter left_shift           =0;
        parameter datawidth8           =1;
        parameter datawidth4           =0;
        parameter twoline              =1;
        parameter oneline              =0;
        parameter font5x10             =1;
        parameter font5x7              =0;
       

       
       
        reg [20:0] clkcnt;
       
        always @ (posedge clk)
        if(!rst)
        clkcnt<=21'b00000_0000_0000_0000_0000;
        else
        begin
                if(clkcnt==21'b01001_1100_0100_0000_0000)
                        clkcnt<=21'b00000_0000_0000_0000_0000;
                else
                        clkcnt<=clkcnt+1;
        end
       
        wire tc_clkcnt;
        assign tc_clkcnt=(clkcnt==21'b01001_1100_0100_0000_0000)?1:0;
       
        reg clkdiv;
        always @ (posedge tc_clkcnt)
        if(!rst)
                clkdiv<=0;
        else
                clkdiv<=~clkdiv;
       
        reg clk_int;
        always @ (posedge clkdiv)
        if(rst==0)
                clk_int<=0;
        else
                clk_int<=~clk_int;
               
        always @ (negedge clkdiv)//下降沿lcd_e输出
        if(!rst)
                lcd_e<=0;
        else
                lcd_e<=~lcd_e;
               
               
        always @ (posedge clk_int or negedge rst)
         begin
                if(!rst)
                begin
                        state<=IDLE;
                        flag<=0;
                        counter<=0;
                        divcounter<=0;
                        address<=0;
                end
                else
                begin
                        case(state)
                        IDLE                :begin
                                                        if(!flag)
                                                          begin
                                                                state<=SETFUNCTION;
                                                                flag<=1'b1;
                                                                counter<=0;
                                                                divcounter<=0;
                                                      end
                                            else if(divcounter<4'd8)//改变移动速度
                                                           begin
                                                            divcounter<=divcounter+1;
                                                            state<=IDLE;
                                                               lcd_rw <=1'b1;
                                                           end
                                                          else
                                                           begin
                                                            divcounter<=0;
                                                                state<=SHIFT;
                                                           end
                                                 end
                        CLEAR                        :begin lcd_rs<=0;lcd_rw<=0;data<=8'b0000_0001;
                                                                        state<=SETMODE;end   
                        SETMODE                        :begin lcd_rs<=0;lcd_rw<=0;data[7:2]<=6'b000001;data[1]<=cur_inc;data[0]<=cur_noshift;
                                                                        state<=SETDDRAM1;end
                        RETURNCURSOR        :begin lcd_rs<=0;lcd_rw<=0;data<=8'b00000010;
                                                                        state<=WRITERAM;end
                        SWITCHMODE                 :begin lcd_rs<=0;lcd_rw<=0;data[7:3]<=5'b00001;data[2]<=open_display;data[1]<=open_cur;data[0]<=blank_cur;
                                                                state<=CLEAR;end
                        SHIFT                        :begin lcd_rs<=0;lcd_rw<=0;data[7:4]<=4'b0001;data[3]<=shift_display;data[2]<=left_shift;data[1:0]<=2'b00;
                                                                state<=IDLE;end
                        SETFUNCTION                :begin lcd_rs<=0;lcd_rw<=0;data[7:5]<=3'b001;data[4]<=datawidth8;data[3]<=twoline;data[2]<=font5x10;data[1:0]<=2'b00;
                                                                state<=SWITCHMODE;end
                        SETCGRAM                :begin lcd_rs<=0;lcd_rw<=0;data<=8'b01000000;state<=IDLE;end
                        SETDDRAM1                :begin
                                          lcd_rs<=0;
                                          lcd_rw<=0;
                                          state<=WRITERAM;
                                           if(counter==0)
                                             data<=8'b1000_0000;
                                            else
                                              data<=8'b1100_0000;
                                         end
                        SETDDRAM2                :begin lcd_rs<=0;lcd_rw<=0;data<=8'b10000000;state<=WRITERAM;end//0x80显示在第一行
                        WRITERAM                :begin
                                          lcd_rs<=1;
                                          lcd_rw<=0;
                                          data<=datain;
                                           if(counter<7'd40)
                                             begin
                                  address = counter+1;
                                   counter=counter+1;
                                   state<=WRITERAM;
                                 end
                               else  if(counter==7'd40)//1602lcd第一行能显示40个字符,可通过左移分别显示出来
                                              begin
                                               state<=SETDDRAM1;
                                                counter<=counter+1;
                                              end
                                 else if(counter<7'd73)
                                  begin
                                  address=counter-'d41+'d8;//-41表示所有字符重新显示在第二行,从第8个字符开始显示
                                   counter=counter+1;
                                   state=WRITERAM;
                                   end
                                   else if(counter<7'd81)
                                    begin
                                      address=counter-7'd81+7'd8;
                                      counter=counter+1;
                                      state<=WRITERAM;
                                     end
                                  else
                                    begin
                                     data<=8'd87;//"W"的ASCII值
                                      state<=SHIFT;
                                    end
                             end                  
                             endcase
                end
        end
char_ram charram(.address(address),.data(datain));

endmodule
maryhu1987 发表于 2011-3-31 21:30:02 | 显示全部楼层
最后一个模块没有给出来
您需要登录后才可以回帖 登录 | 我要注册

本版积分规则

关闭

站长推荐上一条 /1 下一条

QQ|小黑屋|手机版|Archiver|fpga论坛|fpga设计论坛 ( 京ICP备20003123号-1 )

GMT+8, 2025-6-22 19:20 , Processed in 0.078122 second(s), 20 queries .

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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