⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 newlcd.v.bak

📁 FPGA驱动LCD12864显示
💻 BAK
字号:
/*LCD12864显示程序
此程序控制LCD12864液晶屏,IC为KS0108或兼容型号

图形文件获取方法:

 在字模提取V21软件中 ,导入一幅128*64黑白图像.
 * 参数设置:
 * 参数设置->其它选项,选择纵向取模,勾上字节倒序,保留逗号,
 * 取模方式为C51。
 将生成的数组通过keilc等C编译软件,在编译软件中新建一工程,写入源程序如下:
unsigned char code tab[]=
{
//图像数据
}
编译此工程将得到hex文件.在QII中使用lpm_rom宏功能模块中调用此hex文件.
*
*/
module newlcd(clock,rst_n,rs,rw,en,data,lcd_cs);
// I/O口声明
input         clock;    //系统时钟
input         rst_n;    //复位信号
output[1:0]   lcd_cs;   //
output        rs;       //1:数据模式;0:指令模式
output        rw;       //1:读操作;0:写操作
output        en;       //使能信号,写操作时在下降沿将数据送出;读操作时保持高电平
output[7:0]   data;     //LCD数据总线

// I/O寄存器
reg           rs;
reg           en;
reg[1:0]      lcd_cs;
reg[7:0]      data;  

//内部寄存器             
reg[3:0]      state;          //状态机
reg[3:0]      next_state;     
reg[20:0]      div_cnt;        //分频计数器  
reg[9:0]      cnt;            //写操作计数器 
reg           cnt_rst;        //写操作计数器复位信号
wire[7:0]      showdata;       //要显示的数据
reg[1:0]       cs_r;

	reg [2:0] page_addr;
	reg [5:0] row_addr;

//内部网线
wire clk_div;                 //分频时钟
wire clk_divs;
wire page_done;               //写一行数据完成标志位
wire frame_done;              //写一屏数据完成标志位
wire left_done;

//状态机参数
parameter  idle         =4'b0000,
           setbase_1    =4'b0001,
           setbase_2    =4'b0011,
           setmode_1    =4'b0010,
           setmode_2    =4'b0110,
           SETpage_addr_1    =4'b0111,
           SETpage_addr_2    =4'b0101,
           SETrow_addr_1     =4'b1101,
           SETrow_addr_2     =4'b1111,
           write_right_1     =4'b1110,
           write_right_2     =4'b1010,
           write_nextpage_1  =4'b1011,
           write_nextpage_2  =4'b1001,
           wr_data_1         =4'b0100,
           wr_data_2         =4'b1100;
//           set_1        =4'b1000;
     
//******************************代码开始*********************************
assign rw = 1'b0;      //对LCD始终为写操作

//时钟分频
always@(posedge clock or negedge rst_n)
begin
    if(!rst_n)
           div_cnt <=  0;     
          else
           div_cnt <= div_cnt+1'b1;    
end       
 
assign clk_div = (div_cnt[15:0] == 20'h7fff);       
 
//状态机转向
always@(posedge clock or negedge rst_n)
begin
    if(! rst_n)
           state <= idle;
    else if(clk_div)
           state <= next_state;  
           
end

//************************状态机逻辑*********************************

always@(state or page_done or left_done or frame_done or cnt or showdata or page_addr or row_addr or cs_r)
begin
     rs <= 1'b0;
     en <= 1'b0;
     lcd_cs <= cs_r;
     cnt_rst <= 1'b0;
     data <= 8'h0;
     case(state)
          idle:
          begin
                next_state <= setbase_1;
                cnt_rst <= 1'b1;
          end
          
//**************************初始化LCD********************************   
          setbase_1:                               //基本指令操作
          begin
                lcd_cs <= 2'b11;
                next_state <= setbase_2;
                data <= 8'hc0;
                en <= 1'b1;
          end
          
          setbase_2:
          begin
                lcd_cs <= 2'b11;
                next_state <= setmode_1;
                data <= 8'hc0;
          end
 //******************************************************************  
          
          setmode_1:               
          begin                    
                lcd_cs <= 2'b11;
                next_state <= setmode_2;     
                data <= 8'h3f;               
                en <=1'b1;
          end  
          
          setmode_2:
          begin
                next_state <= SETpage_addr_1;
                data <= 8'h3f;  
                          
          end 
           
//******************************************************************    
          SETpage_addr_1:                       //设置页地址
          begin
                next_state <= SETpage_addr_2;
                data <= {5'b10111,page_addr};           
                en <= 1'b1;
          end 
          
          SETpage_addr_2:
          begin
                next_state <= SETrow_addr_1;
                data <= {5'b10111,page_addr};                          
          end 
          
          SETrow_addr_1:                       //设置列地址
          begin
                next_state <= SETrow_addr_2;
                data <= {2'b01,row_addr};       
                en <= 1'b1;                   
          end 
          
          SETrow_addr_2:
          begin
                next_state <= wr_data_1;
                data <= {2'b01,row_addr};           
          
          end 
//******************************************************************  
/* 
          write_right_1:                       //写完左半屏64个,换为右半屏显示
          begin
                next_state <=write_right_2;
                row_addr <= 0;
                          
          end 
          
          write_right_2:          
          begin
                next_state <= SETpage_addr_1;          
          end 
 
//******************************************************************   
          write_nextpage_1:                       //写完全一行128个
          begin
                next_state <=write_nextpage_2;
                 row_addr <= 0;          
          end 
          
          write_nextpage_2:          
          begin
                next_state <= SETpage_addr_1;          
          end 
*/
//******************************************************************        
          wr_data_1:                         //写数据到图形显示区
          begin
                next_state <= wr_data_2;
                rs <= 1'b1;
                en <= 1'b1; 
                data <= showdata;         
          end 
          
          wr_data_2:
          begin
             rs <= 1'b1;
             data <= showdata;
             if(left_done)                     //写完左半屏数据64个                
             begin
               if(page_done)                     //写完一页数据128个
               begin
                    if(frame_done)               //写完一屏数据(8页)
                         next_state <= idle;                      
                    else
                    //     next_state <= write_nextpage_1;    
                    next_state <= SETpage_addr_1;
               end    
             else
              //   next_state <= write_right_1;
                   next_state <= SETpage_addr_1;
             end   
            else
            next_state <=  wr_data_1;  
          end 
          default: next_state <= idle;
     endcase
     

     
end
//********************************************************************
 
always@(posedge clock)
begin
      if(clk_div)
      begin
           if(cnt_rst)
           begin
                cnt <= 0;
           end            
           else if(state == wr_data_2)
                begin
                     cnt <= cnt+1'b1;
                end     
                
      end                        
end
//****************************************************

always@(posedge clock or negedge rst_n)
if(!rst_n)
begin
cs_r <= 2'b01;
page_addr <= 0;
end
 else
  if(clk_div && (state == wr_data_2))
       if(page_done)//
       begin
        cs_r <= 2'b01;
        page_addr <= page_addr + 1'b1;//一页写完时写下一页
        end
        else
        if(left_done)
         begin
          cs_r <= 2'b10;
         end                                

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



//********************************************************************
assign left_done = (cnt[5:0] == 6'd63);                //写完左半屏数据64个
assign page_done = (cnt[6:0] == 7'd127);              //写完一页数据128个
assign frame_done = (cnt[9:4] == 7'h3f);               //写完一屏数据


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

//*******************************************************************
//调用ROM(图片数据)
rom  rom(.address(cnt+'d8),.clock(clock),.q(showdata));

endmodule



⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -