原创 1602 Verilog驱动程序

2010-10-18 20:41 3763 11 17 分类: FPGA/CPLD
  没想到今天晚上写1602程序这么顺利,一个多小时就搞定了,

 程序中用了one-hot编码,用的不是很成熟。1602模块程序接口不是很好,有待改进。


 程序包括lcd1602和lcd1602_test两个模块,lcd1602模块为基本模块,lcd1602_test为测试模块。此液晶显示模块已在EP2C8Q208C8芯片50M晶振条件下测试成功。显示结果为:液晶第一行显示“0123456789ABCDEFGH”,第二行显示“abcdefghijklmnop”(显示内容详见lcd1602_test内调用lcd1602时传递的参数)。


    下面为程序源码。


/******************************************************
//module name:lcd1602
//designer:kang
//date:2010-10-18
//version:1.00
******************************************************/
module lcd1602(
   //input signals
   clk,
   rst,
   addr,
   d1,d2,d3,d4,d5,d6,d7,d8,d9,d10,d11,d12,d13,d14,d15,d16,
   //output signals
   lcd_e,
   lcd_rs,
   lcd_rw,
   lcd_d
   );
//input signals
input clk;
input rst;
input [1:0] addr;
input [7:0] d1,d2,d3,d4,d5,d6,d7,d8,d9,d10,d11,d12,d13,d14,d15,d16;
wire clk;
wire rst;
wire [1:0] addr;
wire [7:0] d1,d2,d3,d4,d5,d6,d7,d8,d9,d10,d11,d12,d13,d14,d15,d16;


//output signals
output lcd_e;
output lcd_rs;
output lcd_rw;
output [7:0] lcd_d;
reg lcd_e;
reg lcd_rs;
reg lcd_rw;
reg [7:0] lcd_d;


parameter DIVNUM=16'd40000;
parameter DELAY=15;
parameter IDLE=0;
parameter SETMOD=1;  //0x38 
parameter CLR=2;  //0x01
parameter SETADDMODE=3; //0X06
parameter SETCURSOR=4; //0X0C
parameter W_ADD=5;
parameter W_DAT1=6;
parameter W_DAT2=7;
parameter W_DAT3=8;
parameter W_DAT4=9;
parameter W_DAT5=10;
parameter W_DAT6=11;
parameter W_DAT7=12;
parameter W_DAT8=13;
parameter W_DAT9=14;
parameter W_DAT10=15;
parameter W_DAT11=16;
parameter W_DAT12=17;
parameter W_DAT13=18;
parameter W_DAT14=19;
parameter W_DAT15=20;
parameter W_DAT16=21;


//internal signals
reg [15:0] counter;
reg clk_en;
reg [21:0] current_state;
reg [21:0] next_state;
reg [7:0] delaynum;
reg [7:0] dat1,dat2,dat3,dat4,dat5,dat6,dat7,dat8,dat9,dat10,dat11,dat12,dat13,dat14,dat15,dat16;
reg [1:0] add;


//counter
always @(posedge clk or negedge rst)
 if(!rst) counter<=16'h0;
 else if(counter==DIVNUM) counter<=16'h0;
 else counter<=counter+1'b1;


//clk_en
always @(posedge clk or negedge rst)
 if(!rst) clk_en<=0;
 else if(counter==DIVNUM) clk_en<=1;
 else clk_en<=0;
 
//lcd_e
always @(posedge clk or negedge rst)
 if(!rst) lcd_e<=0;
 else if(counter<=DIVNUM[15:1]) lcd_e<=1;
 else lcd_e<=0;


//dat1-16
always @(posedge clk)
 begin
 if(current_state[SETCURSOR])
  begin
  add<=addr;
  dat1<=d1;
  dat2<=d2;
  dat3<=d3;
  dat4<=d4;
  dat5<=d5;
  dat6<=d6;
  dat7<=d7;
  dat8<=d8;
  dat9<=d9;
  dat10<=d10;
  dat11<=d11;
  dat12<=d12;
  dat13<=d13;
  dat14<=d14;
  dat15<=d15;
  dat16<=d16;
  end
 end
//current_state
always @(posedge clk or negedge rst)
 if(!rst) current_state<=0;
 else current_state<=next_state;


//next_state 
always @(posedge clk or negedge rst)
 if(!rst)
  begin
  next_state<=0;
  delaynum<=0;
  end
 else if(clk_en)
  begin
  next_state<=0;
  case(1'b1)
  current_state[IDLE]:
   begin
   if(delaynum>=DELAY)
    begin
    next_state[SETMOD]<=1'b1;
    delaynum<=0;
    end
   else
    begin
    next_state[IDLE]<=1'b1;
    delaynum<=delaynum+1'b1;
    end
   end
  current_state[SETMOD]:
   begin
   if(delaynum>=DELAY)
    begin
    next_state[CLR]<=1'b1;
    delaynum<=0;
    end
   else
    begin
    next_state[SETMOD]<=1'b1;
    delaynum<=delaynum+1'b1;
    end
   end
  current_state[CLR]:next_state[SETADDMODE]<=1'b1;
  current_state[SETADDMODE]:next_state[SETCURSOR]<=1'b1;
  current_state[SETCURSOR]:next_state[W_ADD]<=1'b1;
  current_state[W_ADD]:next_state[W_DAT1]<=1'b1;
  current_state[W_DAT1]:next_state[W_DAT2]<=1'b1;
  current_state[W_DAT2]:next_state[W_DAT3]<=1'b1;
  current_state[W_DAT3]:next_state[W_DAT4]<=1'b1;
  current_state[W_DAT4]:next_state[W_DAT5]<=1'b1;
  current_state[W_DAT5]:next_state[W_DAT6]<=1'b1;
  current_state[W_DAT6]:next_state[W_DAT7]<=1'b1;
  current_state[W_DAT7]:next_state[W_DAT8]<=1'b1;
  current_state[W_DAT8]:next_state[W_DAT9]<=1'b1;
  current_state[W_DAT9]:next_state[W_DAT10]<=1'b1;
  current_state[W_DAT10]:next_state[W_DAT11]<=1'b1;
  current_state[W_DAT11]:next_state[W_DAT12]<=1'b1;
  current_state[W_DAT12]:next_state[W_DAT13]<=1'b1;
  current_state[W_DAT13]:next_state[W_DAT14]<=1'b1;
  current_state[W_DAT14]:next_state[W_DAT15]<=1'b1;
  current_state[W_DAT15]:next_state[W_DAT16]<=1'b1;
  current_state[W_DAT16]:next_state[SETCURSOR]<=1'b1;
  default:next_state[IDLE]<=1'b1;
  endcase
  end


//lcd_rs,lcd_rw,lcd_d
always @(posedge clk or negedge rst)
 if(!rst)
  begin
  lcd_rs<=0;
  lcd_rw<=0;
  lcd_d<=0;
  end
 else if(clk_en)
  begin
  case(1'b1)
  current_state[IDLE]:;
  current_state[SETMOD]:
   begin
   lcd_rs<=0;
   lcd_rw<=0;
   lcd_d<=8'h38;
   end
  current_state[CLR]:
   begin
   lcd_rs<=0;
   lcd_rw<=0;
   lcd_d<=8'h01;
   end
  current_state[SETADDMODE]:
   begin
   lcd_rs<=0;
   lcd_rw<=0;
   lcd_d<=8'h06;
   end
  current_state[SETCURSOR]:
   begin
   lcd_rs<=0;
   lcd_rw<=0;
   lcd_d<=8'h0c;
   end
  current_state[W_ADD]:
   begin
   if(add==2'd1)
    begin
    lcd_rs<=0;
    lcd_rw<=0;
    lcd_d<=8'h80;
    end
   else if(add==2'd2)
    begin
    lcd_rs<=0;
    lcd_rw<=0;
    lcd_d<=8'hc0;
    end
   end
  current_state[W_DAT1]:
   begin
   lcd_rs<=1'b1;
   lcd_rw<=0;
   lcd_d<=dat1;
   end
  current_state[W_DAT2]:
   begin
   lcd_rs<=1'b1;
   lcd_rw<=0;
   lcd_d<=dat2;
   end
  current_state[W_DAT3]:
   begin
   lcd_rs<=1'b1;
   lcd_rw<=0;
   lcd_d<=dat3;
   end
  current_state[W_DAT4]:
   begin
   lcd_rs<=1'b1;
   lcd_rw<=0;
   lcd_d<=dat4;
   end
  current_state[W_DAT5]:
   begin
   lcd_rs<=1'b1;
   lcd_rw<=0;
   lcd_d<=dat5;
   end
  current_state[W_DAT6]:
   begin
   lcd_rs<=1'b1;
   lcd_rw<=0;
   lcd_d<=dat6;
   end
  current_state[W_DAT7]:
   begin
   lcd_rs<=1'b1;
   lcd_rw<=0;
   lcd_d<=dat7;
   end
  current_state[W_DAT8]:
   begin
   lcd_rs<=1'b1;
   lcd_rw<=0;
   lcd_d<=dat8;
   end
  current_state[W_DAT9]:
   begin
   lcd_rs<=1'b1;
   lcd_rw<=0;
   lcd_d<=dat9;
   end
  current_state[W_DAT10]:
   begin
   lcd_rs<=1'b1;
   lcd_rw<=0;
   lcd_d<=dat10;
   end
  current_state[W_DAT11]:
   begin
   lcd_rs<=1'b1;
   lcd_rw<=0;
   lcd_d<=dat11;
   end
  current_state[W_DAT12]:
   begin
   lcd_rs<=1'b1;
   lcd_rw<=0;
   lcd_d<=dat12;
   end
  current_state[W_DAT13]:
   begin
   lcd_rs<=1'b1;
   lcd_rw<=0;
   lcd_d<=dat13;
   end
  current_state[W_DAT14]:
   begin
   lcd_rs<=1'b1;
   lcd_rw<=0;
   lcd_d<=dat14;
   end
  current_state[W_DAT15]:
   begin
   lcd_rs<=1'b1;
   lcd_rw<=0;
   lcd_d<=dat15;
   end
  current_state[W_DAT16]:
   begin
   lcd_rs<=1'b1;
   lcd_rw<=0;
   lcd_d<=dat16;
   end
  default:;
  endcase
  end


endmodule
/******************************************************
//module name:lcd1602_test
//designer:kang
//date:2010-10-18
//version:1.00
******************************************************/
module lcd1602_test(
    //input signals
    clk,
    rst,
    //output signals
    LCD_E,
    LCD_RS,
    LCD_RW,
    LCD_D
    );
//input signals
input clk;
input rst;
wire clk;
wire rst;


//output signals
output LCD_E;
output LCD_RS;
output LCD_RW;
output [7:0] LCD_D;
wire LCD_E;
wire LCD_RS;
wire LCD_RW;
wire [7:0] LCD_D;


//internal signals
reg [7:0] dat1,dat2,dat3,dat4,dat5,dat6,dat7,dat8,dat9,dat10,dat11,dat12,dat13,dat14,dat15,dat16;
reg [24:0] counter;
reg [1:0] add;



//counter
always @(posedge clk or negedge rst)
 begin
 if(!rst) counter<=0;
 else if(counter==24'd800000) counter<=0;
 else counter<=counter+1'b1;
 end



//add and data
always @(posedge clk)
 begin
 if(counter<=400000)
  begin
  add<=2'd1;
  dat1<=8'h30;
  dat2<=8'h31;
  dat3<=8'h32;
  dat4<=8'h33;
  dat5<=8'h36;
  dat6<=8'h37;
  dat7<=8'h38;
  dat8<=8'h39;
  dat9<=8'h41;
  dat10<=8'h42;
  dat11<=8'h43;
  dat12<=8'h44;
  dat13<=8'h45;
  dat14<=8'h46;
  dat15<=8'h47;
  dat16<=8'h48;
  end
 else
  begin
  add<=2'd2;
  dat1<=8'h61;
  dat2<=8'h62;
  dat3<=8'h63;
  dat4<=8'h64;
  dat5<=8'h65;
  dat6<=8'h66;
  dat7<=8'h67;
  dat8<=8'h68;
  dat9<=8'h69;
  dat10<=8'h6a;
  dat11<=8'h6b;
  dat12<=8'h6c;
  dat13<=8'h6d;
  dat14<=8'h6e;
  dat15<=8'h6f;
  dat16<=8'h70;
  end
 end


lcd1602 lcd1602(
                clk,
                rst,
                add,
                dat1,dat2,dat3,dat4,dat5,dat6,dat7,dat8,dat9,dat10,dat11,dat12,dat13,dat14,dat15,dat16,
                LCD_E,
                LCD_RS,
                LCD_RW,
                LCD_D
                );


endmodule

PARTNER CONTENT

文章评论6条评论)

登录后参与讨论

用户425426 2012-11-18 14:20

请问一下你的SDRAM调试成功了吗?想请教请教你

用户425426 2012-11-18 14:18

请问一下你的SDRAM调试成功了吗?想请教请教你

用户420241 2012-10-29 10:03

有点乱

用户403866 2011-8-7 20:33

好长呀

用户282447 2010-12-8 21:39

下面有个lcd1602_test,可用来调试。这个1602的接口做的不好,呵呵

用户193497 2010-12-7 15:51

为什么有这么多输入啊,怎么调试呢
相关推荐阅读
用户282447 2011-01-19 17:05
stm32使用fsmc时地址移位问题
stm32平台使用fsmc时,当操作数据宽度为8位时,HADDR【25:0】与FSMC【25:0】对齐,当操作的数据为16位时,HADDR【25:1】与FSMC【24:0】对齐,HADDR【0】未接。...
用户282447 2011-01-05 19:42
verilog分频
fpga程序里经常会遇见给一个50 MHZ的clk,然后产生一个可变频率的clk‘。尤其是在电机控制中,加减速需要便频率,而fpga中除法又比较耗资源。今天看到一个程序,觉得思想不错,整理如下。   ...
用户282447 2011-01-01 23:47
2011,回顾从前
毕业第一年。    2010很快过去了,大学生活也已经成了历史,貌似很近,又貌似很远。    2011已经来临,是时候该回顾回顾自己大学至今都在做什么了。俗话说,男的把电脑当游戏机,女的把电脑当影碟机...
用户282447 2010-12-24 11:33
sdram verilog程序
sdram芯片用的是hy57v641620hgt-7,fpga用的是EP1C6Q240C8,晶振是50M,经过PLL倍频至125M,系统clk时钟是125M,sdram时钟相移-3ns程序是根据特权的...
用户282447 2010-12-24 11:26
串口verilog程序
发一个自己写的串口程序,波特率115200,一位起始位,8个数据位,一个停止位接收采用8倍过采样。下面有4个module,uart是顶层模块,uart_rx是接收模块,uart_tx是发送模块,uar...
用户282447 2010-11-27 18:58
tft verilog驱动
       使用的TFT为群创7寸液晶屏AT070TN83,分辨率为800*480FPGA为ep1c6q240c8,晶振为50M       首先介绍一下TFT接口       1和2脚VLED,4...
我要评论
6
11
关闭 站长推荐上一条 /3 下一条