集成电路技术分享

 找回密码
 我要注册

QQ登录

只需一步,快速开始

搜索
查看: 1855|回复: 1

求VHDL编写的LCD液晶显示程序

[复制链接]
lichangyun 发表于 2010-11-20 10:58:16 | 显示全部楼层 |阅读模式
想要在HS12864液晶显示器上显示一字符A,自写的程序如下:(内部时钟为50MHZ)
  entity lcd_8 is
    Port ( clk : in  STD_LOGIC;
           reset : in  STD_LOGIC;
           rs : out  STD_LOGIC;
           rw : out  STD_LOGIC;
           en : out  STD_LOGIC;
           data : out  STD_LOGIC_VECTOR (7 downto 0));
end lcd_8;

architecture Behavioral of lcd_8 is         
type istate is (
                  write_instr,
        write_data8,
         set_addr,                       
          ret_home                                       
                                                    );
        signal state:istate;
    signal q : std_logic_vector(24 downto 0);
    signal clk1 :std_logic;
    signal cnt :std_logic_vector(2 downto 0);
            begin
         en<=clk1;
         rw<='0';
        process(clk,reset)
           begin
                  if(reset='1') then
                    q<=(others=>'0');
                        elsif(rising_edge(clk)) then
                           q <= q + 1;
                  end if;
          clk1<=q(15);         
   end process;
    process(clk1,reset)
        begin
         if(reset='1')then
           state<=write_instr;
                 rs<='0';
                 cnt<="000";
                 elsif(rising_edge(clk1))then
                      if(cnt="111")then
                                         cnt<="000";
                                        else
                           cnt<=cnt+1;
                                          end if;                                                                       
                        case state is
                          when write_instr=>
                             
                             rs<='0';
                                  case cnt is
                                        
                                             when "000"=>data<="00110000";
                                                  when "001" =>data<="00000110";
                                                  when "010" =>data<="00001100";
                                                  when "011" =>data<="00000001";
                                                 when others =>data<="00000000";
                                                 
                                        end case;
                                        state<=write_data8;               
                                when write_data8=>
                                                      rs<='1';
                                         data<="01000001";
                                state<=        set_addr;
                  when set_addr=>
                           rs<='0';
                            data<="10000000";
                          state<= ret_home;
                   when ret_home=>
                rs<='0';
                               data<="00000010";
                               state<=write_data8;
                when others=>
                                         state<=write_instr;
                           end case;
           end if;
         end process;

end Behavioral;
程序已经仿真成功,但是无法配置引脚,下载进去之后,LCD只显示方格而不显示字符,恳请大家帮忙看看,或是给一可以显示的程序
fpgaw 发表于 2011-1-4 11:47:34 | 显示全部楼层
** 文件名称:       LCD_Top.v

** 创建者:     

** 创建日期:       2008  

** 版本号:         V3.0

** 功能描述:    按键检测

**

**--------------------------------------修改文件的相关信息--------------------------------------------------

** 修改人:  

** 修改日期:  

** 版本号:  

** 修改内容:  

**

*******************************************************************************/

// LCD_Top.v

//连接Clock_Gen模块和LCD_Driver模块

module LCD_Top(clk_48M,rst,LCD_EN,RS,RW,DB8);

input   clk_48M,rst;
output  LCD_EN,RS,RW;
output  [7:0] DB8;
wire    clk_LCD;    //用于将Clock_Gen模块clk_LCD输出连接至LCD_Driver模块的clk_LCD输入

Clock_Gen   U1(.clk_48M(clk_48M),
               .rst(rst),
               .clk_LCD(clk_LCD));

LCD_Driver  U2(.clk_LCD(clk_LCD),
               .rst(rst),
               .LCD_EN(LCD_EN),
               .RS(RS),
               .RW(RW),
               .DB8(DB8));
               
endmodule

// Clock_Gen.v

/****************为LCD_Drvier模块产生500Hz的时钟信号**************/

module Clock_Gen(clk_48M,rst,clk_LCD);

input   clk_48M,rst;                //rst为全局复位信号(高电平有效)              
output  clk_LCD;   

wire    clk_counter;
reg     [11:0]  cnt;                  //对时钟进行计数分频
wire    clk_equ;
reg     [9:0] count;
reg     clk_BUF;
parameter       counter= 50;     //多少分频
/********************************************************************************
** 模块名称:分频器
** 功能描述:通过计数器实现分频功能.
********************************************************************************/

always@(posedge clk_48M)
begin
if(!rst)                            //低电平复位
  cnt <= 12'd0;
else
if(clk_equ)
  cnt <= 12'd0;
else
     cnt <= cnt+1'b1;
end

assign clk_equ = (cnt==counter);
assign clk_counter = clk_equ;               
always @(posedge clk_counter or negedge rst)
begin                                   //利用计数器分频产生500Hz时钟
    if(!rst)
        begin
            clk_BUF <= 1'b0;
            count <= 10'b0;
        end
    else
    begin   
        if(count == 10'd1000)
            begin
                clk_BUF <= ~clk_BUF;
                count <= 10'b0;
            end     
        else
            begin
                clk_BUF <= clk_BUF;     //clk_BUF为500Hz的时钟信号
                count <= count + 1'b1;
            end
    end
end

assign  clk_LCD = clk_BUF;
//clk_LCD为LCD_Drvier模块所需要的500Hz的时钟信号

endmodule

// LCD_Driver.v

//功能简述:在1602液晶模块上显示字符串,其中第一行显示“Welcom to hx"
//                                        在第二行显示“www.mcuhx.com"
//液晶模块为TC1602A,相关特性请参考其数据手册

module LCD_Driver(clk_LCD,rst,LCD_EN,RS,RW,DB8);

input   clk_LCD,rst;        //rst为全局复位信号(高电平有效)

output  LCD_EN,RS,RW;

//LCD_EN为LCD模块的使能信号(下降沿触发)
//RS=0时为写指令;RS=1时为写数据
//RW=0时对LCD模块执行写操作;RW=1时对LCD模块执行读操作

output  [7:0] DB8;          //8位指令或数据总线

reg     [7:0] DB8;
reg     [111:0] Data_First_Buf,Data_Second_Buf;     //液晶显示的数据缓存
reg     RS,LCD_EN_Sel;
reg     [3:0] disp_count;
reg     [3:0] state;

parameter   Clear_Lcd = 4'b0000,                            //清屏并光标复位
            Set_Disp_Mode = 4'b0001,                        //设置显示模式:8位2行5x7点阵   
            Disp_On = 4'b0010,                              //显示器开、光标不显示、光标不允许闪烁
            Shift_Down = 4'b0011,                           //文字不动,光标自动右移
            Write_Addr = 4'b0100,                           //写入显示起始地址
            Write_Data_First = 4'b0101,                     //写入第一行显示的数据
            Write_Data_Second = 4'b0110,                    //写入第二行显示的数据
            Idel = 4'b0111;                                 //空闲状态

parameter   Data_First = "welcome to hx",                  //液晶显示的第一行的数据
            Data_Second = "www.mcuhx.com";                 //液晶显示的第二行的数据         


assign  RW = 1'b0;                     //RW=0时对LCD模块执行写操作
assign  LCD_EN = LCD_EN_Sel ? clk_LCD : 1'b0;

//通过LCD_EN_Sel信号来控制LCD_EN的开启与关闭

always @(posedge clk_LCD or negedge rst)
begin
   if(!rst)
      begin
          state <= Clear_Lcd;                               //复位:清屏并光标复位   
          RS <= 1'b0;                                       //复位:RS=0时为写指令;                       
          DB8 <= 8'b0;                                      //复位:使DB8总线输出全0
          LCD_EN_Sel <= 1'b1;                               //复位:开启夜晶使能信号
          //Data_First_Buf <= Data_First;
          //Data_Second_Buf <= Data_Second;
          disp_count <= 4'b0;
      end
   else
      case(state)                                           //初始化LCD模块
      Clear_Lcd:
             begin
                state <= Set_Disp_Mode;
                DB8 <= 8'b00000001;                         //清屏并光标复位   
             end
      Set_Disp_Mode:
             begin
                state <= Disp_On;
                DB8 <= 8'b00111000;                         //设置显示模式:8位2行5x8点阵         
             end
      Disp_On:
             begin
                state <= Shift_Down;
                DB8 <= 8'b00001100;                         //显示器开、光标不显示、光标不允许闪烁   
             end
      Shift_Down:
            begin
                state <= Write_Addr;
                DB8 <= 8'b00000110;                         //文字不动,光标自动右移   
            end
      Write_Addr:
            begin
                state <= Write_Data_First;
                DB8 <= 8'b10000001;                         //写入第一行显示起始地址:第一行第二个位置   
                Data_First_Buf <= Data_First;               //将第一行显示的数据赋给Data_First_Buf?
            end
      Write_Data_First:                                     //写第一行数据
            begin
                if(disp_count == 14)                        //disp_count等于14时表示第一行数据已写完
                    begin
                        DB8 <= 8'b11000001;                 //送入写第二行的指令
                        RS <= 1'b0;
                        disp_count <= 4'b0;
                        Data_Second_Buf <= Data_Second;
                        state <= Write_Data_Second;         //写完第一行进入写第二行状态
                    end
                else
                    begin
                        DB8 <= Data_First_Buf[111:104];
                        Data_First_Buf <= (Data_First_Buf << 8);
                        RS <= 1'b1;                         //RS=1表示写数据
                        disp_count <= disp_count + 1'b1;
                        state <= Write_Data_First;
                    end
            end
      Write_Data_Second:                                    //写第二行数据
            begin
                if(disp_count == 14)
                    begin
                        LCD_EN_Sel <= 1'b0;
                        RS <= 1'b0;
                        disp_count <= 4'b0;
                        state <= Idel;                      //写完进入空闲状态
                    end
                else
                    begin
                        DB8 <= Data_Second_Buf[111:104];
                        Data_Second_Buf <= (Data_Second_Buf << 8);
                        RS <= 1'b1;
                        disp_count <= disp_count + 1'b1;
                        state <= Write_Data_Second;
                    end              
            end
      Idel:     
            begin
                state <=  Idel;                             //在Idel状态循环  
            end
      default:  state <= Clear_Lcd;                         //若state为其他值,则将state置为Clear_Lcd
      endcase
end

endmodule
您需要登录后才可以回帖 登录 | 我要注册

本版积分规则

关闭

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

QQ|小黑屋|手机版|Archiver|集成电路技术分享 ( 京ICP备20003123号-1 )

GMT+8, 2024-5-17 16:33 , Processed in 0.070256 second(s), 19 queries .

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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