|
新近写的,水平有限,欢迎拍砖。
实验程序:
---------------------------------------------------
module lcd1602_drive(
input clk,
input rst_n,
// LCD1602 Interface
output reg [7:0] lcd_data,
output lcd_e,
output reg lcd_rs,
output lcd_rw
);
// +++++++++++++++++++++++++++++++++++++
// 分频模块开始
// +++++++++++++++++++++++++++++++++++++
parameter CLK_DIV = 10_0000; // 分频参数
reg [16:0] cnt; // 分频计数子
reg lcd_clk; // 500Hz
// 将50MHz板载时钟分频至500Hz
// 注:计数分频,非等占空比
always @(posedge clk, negedge rst_n)
begin
if(!rst_n)
begin cnt <= 1'b0; lcd_clk <= 0; end
else
begin
if(cnt <= CLK_DIV)
begin cnt <= cnt + 1'b1; lcd_clk <= 1; end
else
begin cnt <= 1'b0; lcd_clk <= 0; end
end
end
// -------------------------------------
// 分频模块结束
// -------------------------------------
// +++++++++++++++++++++++++++++++++++++
// LCD1602驱动模块开始
// +++++++++++++++++++++++++++++++++++++
/*
* 格雷码编码
* 状态数:初始化5个;换行1个;数据32个;空闲1个;共39个。
*/
// 初始化
parameter INIT_0 = 8'h00;
parameter INIT_1 = 8'h01;
parameter INIT_2 = 8'h03;
parameter INIT_3 = 8'h02;
parameter INIT_4 = 8'h06;
// 显示第一行
parameter ROW1_0 = 8'h07;
parameter ROW1_1 = 8'h05;
parameter ROW1_2 = 8'h04;
parameter ROW1_3 = 8'h0C;
parameter ROW1_4 = 8'h0D;
parameter ROW1_5 = 8'h0F;
parameter ROW1_6 = 8'h0E;
parameter ROW1_7 = 8'h0A;
parameter ROW1_8 = 8'h0B;
parameter ROW1_9 = 8'h09;
parameter ROW1_A = 8'h08;
parameter ROW1_B = 8'h18;
parameter ROW1_C = 8'h19;
parameter ROW1_D = 8'h1B;
parameter ROW1_E = 8'h1A;
parameter ROW1_F = 8'h1E;
// 换行
parameter CH_ROW = 8'h1F;
// 显示第二行
parameter ROW2_0 = 8'h1D;
parameter ROW2_1 = 8'h1C;
parameter ROW2_2 = 8'h14;
parameter ROW2_3 = 8'h15;
parameter ROW2_4 = 8'h17;
parameter ROW2_5 = 8'h16;
parameter ROW2_6 = 8'h12;
parameter ROW2_7 = 8'h13;
parameter ROW2_8 = 8'h11;
parameter ROW2_9 = 8'h10;
parameter ROW2_A = 8'h30;
parameter ROW2_B = 8'h31;
parameter ROW2_C = 8'h33;
parameter ROW2_D = 8'h32;
parameter ROW2_E = 8'h36;
parameter ROW2_F = 8'h37;
// 空闲
parameter IDLE = 8'h35;
reg [5:0] current_state, next_state; // 现态、次态
// FSM: always1
always @ (posedge lcd_clk, negedge rst_n)
if(!rst_n) current_state <= INIT_0;
else current_state <= next_state;
// FSM: always2
always
begin
case(current_state)
// 初始化
INIT_0 : next_state = INIT_1;
INIT_1 : next_state = INIT_2;
INIT_2 : next_state = INIT_3;
INIT_3 : next_state = INIT_4;
INIT_4 : next_state = ROW1_0;
// 显示第一行
ROW1_0 : next_state = ROW1_1;
ROW1_1 : next_state = ROW1_2;
ROW1_2 : next_state = ROW1_3;
ROW1_3 : next_state = ROW1_4;
ROW1_4 : next_state = ROW1_5;
ROW1_5 : next_state = ROW1_6;
ROW1_6 : next_state = ROW1_7;
ROW1_7 : next_state = ROW1_8;
ROW1_8 : next_state = ROW1_9;
ROW1_9 : next_state = ROW1_A;
ROW1_A : next_state = ROW1_B;
ROW1_B : next_state = ROW1_C;
ROW1_C : next_state = ROW1_D;
ROW1_D : next_state = ROW1_E;
ROW1_E : next_state = ROW1_F;
ROW1_F : next_state = CH_ROW;
// 换行
CH_ROW : next_state = ROW2_0;
// 显示第二行
ROW2_0 : next_state = ROW2_1;
ROW2_1 : next_state = ROW2_2;
ROW2_2 : next_state = ROW2_3;
ROW2_3 : next_state = ROW2_4;
ROW2_4 : next_state = ROW2_5;
ROW2_5 : next_state = ROW2_6;
ROW2_6 : next_state = ROW2_7;
ROW2_7 : next_state = ROW2_8;
ROW2_8 : next_state = ROW2_9;
ROW2_9 : next_state = ROW2_A;
ROW2_A : next_state = ROW2_B;
ROW2_B : next_state = ROW2_C;
ROW2_C : next_state = ROW2_D;
ROW2_D : next_state = ROW2_E;
ROW2_E : next_state = ROW2_F;
ROW2_F : next_state = IDLE;
// 空闲
IDLE : next_state = IDLE;
default : next_state = INIT_0;
endcase
end
// FSM: always3
always @ (posedge lcd_clk, negedge rst_n)
begin
if(!rst_n)
begin lcd_rs <= 0; lcd_data <= 8'h00; end
else
begin
case(current_state)
INIT_0, CH_ROW, IDLE: lcd_rs <= 0;// 开始写指令
ROW1_0, ROW2_0 : lcd_rs <= 1;// 开始写数据
endcase
case(current_state)
// 写指令,初始化
INIT_0 : lcd_data <= 8'h38;
INIT_1 : lcd_data <= 8'h0C;
INIT_2 : lcd_data <= 8'h01;
INIT_3 : lcd_data <= 8'h06;
INIT_4 : lcd_data <= 8'H80;
// 写数据,显示第一行
ROW1_0 : lcd_data <= "a";
ROW1_1 : lcd_data <= "b";
ROW1_2 : lcd_data <= "c";
ROW1_3 : lcd_data <= "d";
ROW1_4 : lcd_data <= "e";
ROW1_5 : lcd_data <= "f";
ROW1_6 : lcd_data <= "g";
ROW1_7 : lcd_data <= "h";
ROW1_8 : lcd_data <= "i";
ROW1_9 : lcd_data <= "j";
ROW1_A : lcd_data <= "k";
ROW1_B : lcd_data <= "l";
ROW1_C : lcd_data <= "m";
ROW1_D : lcd_data <= "n";
ROW1_E : lcd_data <= "o";
ROW1_F : lcd_data <= "p";
// 写指令,换行
CH_ROW : lcd_data <= 8'hC0;
// 写数据,显示第二行
ROW2_0 : lcd_data <= "A";
ROW2_1 : lcd_data <= "B";
ROW2_2 : lcd_data <= "C";
ROW2_3 : lcd_data <= "D";
ROW2_4 : lcd_data <= "E";
ROW2_5 : lcd_data <= "F";
ROW2_6 : lcd_data <= "G";
ROW2_7 : lcd_data <= "H";
ROW2_8 : lcd_data <= "I";
ROW2_9 : lcd_data <= "J";
ROW2_A : lcd_data <= "K";
ROW2_B : lcd_data <= "L";
ROW2_C : lcd_data <= "M";
ROW2_D : lcd_data <= "N";
ROW2_E : lcd_data <= "O";
ROW2_F : lcd_data <= "P";
// 写指令,空闲
IDLE : lcd_data <= 8'h00;
endcase
end
end
// 在时钟高电平有效,低电平失效
// 数据方可被锁存
assign lcd_e = lcd_clk;
assign lcd_rw = 1'b0; // 只写
// -------------------------------------
// LCD1602驱动模块结束
// -------------------------------------
endmodule
---------------------------------------------------
实验现象:
(原文件名:抓图-1.png)
Quartus II 综合报告:
(原文件名:抓图-2.png) |
阿莫论坛20周年了!感谢大家的支持与爱护!!
知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)
|