今天的课程——1602lcd的文字循环显示

上一篇 / 下一篇  2008-07-13 18:50:40

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] data;
 
 reg [10:0] state;
 reg flag;
 reg [5:0] address;
 
 
 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 SETDDRAM =11'b00010000000;  //设置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;

 function [7:0] ddram;
  input [5:0] addr;
  begin
   case(addr)
   6'b000_000:ddram=8'b0101_1001;//Y
   6'b000_001:ddram=8'b0110_1111;//o
   6'b000_010:ddram=8'b0111_0101;//u
   6'b000_011:ddram=8'b0010_0000;//_
   6'b000_100:ddram=8'b0110_0001;//a
   6'b000_101:ddram=8'b0111_0010;//r
   6'b000_110:ddram=8'b0110_0101;//e
   6'b000_111:ddram=8'b0010_0000;//_
   6'b001_000:ddram=8'b0111_0111;//w
   6'b001_001:ddram=8'b0110_0101;//e
   6'b001_010:ddram=8'b0110_1100;//l
   6'b001_011:ddram=8'b0110_0011;//c
   6'b001_100:ddram=8'b0110_1111;//o
   6'b001_101:ddram=8'b0110_1101;//m
   6'b001_110:ddram=8'b0110_0101;//e
   6'b001_111:ddram=8'b0010_0001;//!
   endcase
  end
 endfunction
 
 reg [15:0] clkcnt;
 
 always @ (posedge clk)
 if(!rst)
 clkcnt<=16'b0000_0000_0000_0000;
 else
 begin
  if(clkcnt==20000)//clkcnt为模40000计数器
   clkcnt<=16'b0000_0000_0000_0000;
  else
   clkcnt<=clkcnt+1;
 end
 
 wire tc_clkcnt;
 assign tc_clkcnt=(clkcnt==20000)?1:0;//对clk40000分频
 
 reg clkdiv;
 always @ (posedge tc_clkcnt)
 if(!rst)
  clkdiv<=0;
 else
  clkdiv<=~clkdiv;//对clk80000分频
 
 reg clk_int;
 always @ (posedge clkdiv)
 if(rst==0)
  clk_int<=0;
 else
  clk_int<=~clk_int;//对clk160000分频
  
 always @ (negedge clkdiv)
 if(rst==0)
  lcd_e<=0;
 else
  lcd_e<=~lcd_e;//对clk160000分频
  
  
 always @ (posedge clk_int or negedge rst)
  if(!rst)
  begin
   state<=IDLE;
   address<=6'b000_000;
   flag<=0;
  end
  else
  begin
   case(state)
   IDLE  :begin
       data<=8'bzzzz_zzzz;
       if(flag==0)
       begin
        state<=SETFUNCTION;
        flag<=1;
       end
       else
          
        state<=IDLE;
       end
   CLEAR   :begin lcd_rs<=0;lcd_rw<=0;data<=8'b0000_0001;
         state<=SETDDRAM;end  
   SETMODE   :begin lcd_rs<=0;lcd_rw<=0;data[7:2]<=6'b000001;data[1]<=cur_inc;data[0]<=cur_noshift;
         state<=WRITERAM;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]<=1;data[1]<=0;data[0]<=0;
        state<=CLEAR;end
   SHIFT   :begin lcd_rs<=0;lcd_rw<=0;data[7:4]<=4'b0001;data[3]<=1;data[2]<=1;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
   SETDDRAM  :begin
                   if(address==6'b001111) begin
                    lcd_rs<=0;lcd_rw<=0;data<=8'b11001111;state<=WRITERAM;
                   end
                   else begin
                   lcd_rs<=0;lcd_rw<=0;data<=8'b11000000;state<=WRITERAM;
                   end
                   end
   WRITERAM  :begin
        lcd_rs<=1;
        lcd_rw<=0;
        data<=ddram(address);
        if(address!==6'b001_111)
           begin
        address<=address+1;
        state<=WRITERAM;
        end
           else
       begin
        state<=SETDDRAM;
        //address<=6'b000_000;
       end
       end
   endcase
  end
endmodule
  


TAG:

dyl_1988的个人空间 引用 删除 dyl_1988   /   2008-07-18 10:16:53
狠啊,怎么编的,能教教我吗?我在学FPGA,不知道怎么驱动LCD显示....迷茫中
dyl_1988的个人空间 引用 删除 dyl_1988   /   2008-07-18 10:16:47
5
引用 删除 ancent   /   2008-07-16 10:23:23
虽然只有一篇日志,也踩一下
 

评分:0

我来说两句

显示全部

:loveliness: :handshake :victory: :funk: :time: :kiss: :call: :hug: :lol :'( :Q :L ;P :$ :P :o :@ :D :( :)

日历

« 2008-10-04  
   1234
567891011
12131415161718
19202122232425
262728293031 

数据统计

  • 访问量: 319
  • 日志数: 5
  • 建立时间: 2008-07-11
  • 更新时间: 2008-09-24

RSS订阅

Open Toolbar