10、 LCD24064的显示
1、 实验内容
LCD24064的显示
2、 实验代码
`define DEBUG
`ifdef DEBUG
`define COUNT 17'd5
`else
`define COUNT 17'd10000
`endif
module lcd12864(
CLK_50MHZ,
RESET_N,
LCD_RS,
LCD_RW,
LCD_E,
LCD_D,
RED
);
output RED;
input CLK_50MHZ; //系统时钟
input RESET_N; //复位信号
output [7:0] LCD_D; //LCD数据总线
output LCD_RS; //1:数据模式;0:指令模式
output LCD_RW; //1:读操作;0:写操作,
output LCD_E; //使能信号,写操作时在下降沿将数据送出;读操作时保持高电平
//output rst;//lcd复位信号
//内部寄存器
reg [7:0] LCD_D;
reg LCD_RS;
//状态定义
parameter FUNCTION = 4'h0;
parameter DISPLAY = 4'h1;
parameter MODE = 4'h2;
parameter CLEAR = 4'h3;
parameter WRITERAM0 = 4'h4;
parameter WRITERAM1 = 4'h5;
parameter WRITERAM2 = 4'h6;
parameter WRITERAM3 = 4'h7;
parameter SETDDRAM0 = 4'h8;
parameter SETDDRAM1 = 4'h9;
parameter SETDDRAM2 = 4'ha;
parameter SETDDRAM3 = 4'hb;
parameter SHIFT = 4'hc;
function [7:0] ddram;
input [5:0] n;
begin
case(n)
//发送第1行数据
6'b000_000:ddram = "W";
6'b000_001:ddram = "e";
6'b000_010:ddram = "l";
6'b000_011:ddram = "c";
6'b000_100:ddram = "o";
6'b000_101:ddram = "m";
6'b000_110:ddram = "e";
6'b000_111:ddram = " ";
6'b001_000:ddram = "F";
6'b001_001:ddram = "P";
6'b001_010:ddram = "G";
6'b001_011:ddram = "A";
6'b001_100:ddram = 8'D0;
//发送第2行数据
6'b001_101:ddram = "s";
6'b001_110:ddram = "d";
6'b001_111:ddram = "j";
6'b010_000:ddram = "n";
6'b010_001:ddram = "t";
6'b010_010:ddram = "l";
6'b010_011:ddram = 8'D0;
//发送第3行数据
6'b010_100:ddram = 8'hB5;
6'b010_101:ddram = 8'hE7;
6'b010_110:ddram = 8'hD7;
6'b010_111:ddram = 8'hD3;
6'b011_000:ddram = 8'hB2;
6'b011_001:ddram = 8'hFA;
6'b011_010:ddram = 8'hC6;
6'b011_011:ddram = 8'hB7;
6'b011_100:ddram = 8'hCA;
6'b011_101:ddram = 8'hC0;
6'b011_110:ddram = 8'hBD;
6'b011_111:ddram = 8'hE7;
6'b100_000:ddram = 8'hB7;
6'b100_001:ddram = 8'D0;
//发送第4行数据
6'b100_010:ddram = "w";
6'b100_011:ddram = "w";
6'b100_100:ddram = "w";
6'b100_101:ddram = ".";
6'b100_110:ddram = "e";
6'b100_111:ddram = "e";
6'b101_000:ddram = "p";
6'b101_001:ddram = "w";
6'b101_010:ddram = ".";
6'b101_011:ddram = "c";
6'b101_100:ddram = "o";
6'b101_101:ddram = "m";
6'b101_110:ddram = ".";
6'b101_111:ddram = "c";
6'b110_000:ddram = "n";
6'b110_001:ddram = 8'D0;
endcase
end
endfunction
//*************************代码开始******************************
//工作灯指示
reg [25:0] led_cnt;
always @(posedge CLK_50MHZ or negedge RESET_N)
begin
if(!RESET_N)
led_cnt <= 0;
else
led_cnt <= led_cnt+1'b1;
end
assign RED = led_cnt[25];
//时钟分频
wire clkr;
reg [16:0] counter;
always @(posedge CLK_50MHZ or negedge RESET_N)
begin
if(!RESET_N)
begin
counter <= 17'd0;
end
else if(counter == `COUNT)
counter <= 17'd0;
else
counter <= counter+1'b1;
end
assign clkr = (counter == `COUNT) ;
reg e;
reg [7:0] current = 0;
reg [1:0] cnt;
reg [5:0] address = 0;
always @(posedge clkr)
begin
case(current)
FUNCTION: begin LCD_RS <= 0; LCD_D <= 8'h30; current <= DISPLAY; end //初始化 --基本指令集
DISPLAY: begin LCD_RS <= 0; LCD_D <= 8'h0c; current <= MODE; end //开整体显示 游标关
MODE: begin LCD_RS <= 0; LCD_D <= 8'h06; current <= CLEAR; end //光标右移 DDRAM 地址计数加1 画面整体不移动
CLEAR: begin LCD_RS <= 0; LCD_D <= 8'h01; current <= SETDDRAM0; end //清屏
SETDDRAM0: begin LCD_RS <= 0; LCD_D <= 8'h80; current <= WRITERAM0; end //设置坐标位置 (地址设置为第1行) 设定DDRAM地址80
WRITERAM0:
begin
if(ddram(address))
begin
LCD_RS <= 1;
LCD_D <= ddram(address);
address <= address + 1'b1;
end
else
begin
LCD_RS <= 0;
address <= address + 1'b1;
current <= SETDDRAM1;
end
end
SETDDRAM1: begin LCD_RS <= 0; LCD_D <= 8'h90; current <= WRITERAM1; end //address <= 0;设置坐标位置 (地址设置为第3行)
WRITERAM1:
begin
if(ddram(address))
begin
LCD_RS <= 1;
LCD_D <= ddram(address);
address <= address + 1'b1;
end
else
begin
LCD_RS <= 0;
address <= address + 1'b1;
current <= SETDDRAM2;
end
end
SETDDRAM2: begin LCD_RS<=0; LCD_D<=8'h88; current<=WRITERAM2; end //设置坐标位置 (地址设置为第3行)
WRITERAM2:
begin
if(ddram(address))
begin
LCD_RS <= 1;
LCD_D <= ddram(address);
address <= address + 1'b1;
end
else
begin
LCD_RS <= 0;
address <= address + 1'b1;
current <= SETDDRAM3;
end
end
SETDDRAM3: begin LCD_RS <= 0; LCD_D <= 8'h98; current <= WRITERAM3; end //address <= 0;设置坐标位置 (地址设置为第3行)
WRITERAM3:
begin
if(ddram(address))
begin
LCD_RS <= 1;
LCD_D <= ddram(address);
address <= address + 1'b1;
end
else
begin
LCD_RS <= 0;
address <= address + 1'b1;
current <= SHIFT;
end
end
SHIFT: begin LCD_RS <= 0; LCD_D <= 8'h00; //这段保证前段显示部分至少执行一遍
address <= 0; //然后把液晶的En脚拉高,完成一次读写过程
if(cnt!=2'h2)
begin
e <= 0;
current <= FUNCTION;
cnt <= cnt+1;
end
else
begin
current <= FUNCTION;
e <= 1;
cnt <= 0;
end
end
default: current <= SHIFT;
endcase
end
assign LCD_E = clkr | e;//对LCD始终为写操作
assign LCD_RW = 0; //对LCD始终为写操作
//assign rst=RESET_N;
endmodule
3、 测试仿真
// Verilog Test Bench template for design : lcd12864
//
// Simulation tool : ModelSim-Altera (Verilog)
//
`timescale 1 ps/ 1 ps
module lcd12864_vlg_tst();
// constants
// general purpose registers
//reg eachvec;
// test vector input registers
reg CLK_50MHZ;
reg RESET_N;
// wires
wire [7:0] LCD_D;
wire LCD_E;
wire LCD_RS;
wire LCD_RW;
// assign statements (if any)
lcd12864 i1 (
// port map - connection between master ports and signals/registers
.CLK_50MHZ(CLK_50MHZ),
.LCD_D(LCD_D),
.LCD_E(LCD_E),
.LCD_RS(LCD_RS),
.LCD_RW(LCD_RW),
.RESET_N(RESET_N)
);
initial
begin
CLK_50MHZ = 0;
RESET_N = 0;
#20
RESET_N = 1;
end
initial
begin
forever
#20
CLK_50MHZ =~CLK_50MHZ;
end
endmodule
4、 测试下载文件
lcd12864.rar