FPGA1602液晶显示的各个程序

 

前几天参加学校的FPGA比赛,做的是频率检测器,就2天时间,做的还可以,从1HZ到1MHZ,结果用1602液晶显示,还没有整理好,等整理好了也拿出来,先把1602液晶显示部分整理了下,拿出来和大家分享,我用的板子是EP1C3T144C8N,时钟是24MHZ跑起来没有问题。

代码我还是贴上来,直接上了……..

顶层模块 lcd.v

`timescale 1ns / 1ps

module lcd (clk,sys_rst_n,lcd_en,lcd_rs,lcd_rw,lcd_data);
input clk; //时钟24MHz,周期为41.6ns
input sys_rst_n; //系统复位信号,低电平复位
output lcd_en; //使能信号,1时读取信息,1→0(下降沿)执行指令
output lcd_rs; // 0=输入指令,1=输入数据
output lcd_rw; //0=向LCD写入指令或数据,1=从LCD读取信息
output[7:0] lcd_data; //LCD数据信号

wire clk_lcd; //用于将clk_div模块输出的clk_lcd链接到lcd_ctrl中

clk_div U1(.clk(clk),
		   .sys_rst_n(sys_rst_n),
		   .clk_lcd(clk_lcd)
		   );

lcd_ctrl U2(.clk_lcd(clk_lcd),
			.sys_rst_n(sys_rst_n),
			.lcd_en(lcd_en),
			.lcd_rs(lcd_rs),
			.lcd_rw(lcd_rw),
			.lcd_data(lcd_data)
			);

endmodule


 

分频模块clk_div.v

`timescale 1ns / 1ps

module clk_div(clk,sys_rst_n,
			   clk_lcd
			   );

input clk;
input sys_rst_n; //sys_rst_n为全局复位信号(高电平有效)
output clk_lcd; //clk_lcd链接到lcd_ctrl中

reg [19:0] cnt; //对时钟进行计数分频
reg clk_BUF;

/********************************************************************************
** 模块名称:分频器
** 功能描述:通过计数器实现分频功能.
********************************************************************************/
always @ (posedge clk or negedge sys_rst_n)
if(!sys_rst_n) //低电平复位
	cnt <= 20'd0;
else if(cnt >= 26026) //学习特权同学,提高代码健壮性
	cnt <= 20'd0;
else
	cnt <= cnt+1'b1;

always @ (posedge clk or negedge sys_rst_n)
if(!sys_rst_n)
	clk_BUF <= 0;
else if(cnt == 26026)
	clk_BUF <= ~clk_BUF;

assign clk_lcd = clk_BUF;

endmodule


 

 

液晶显示控制模块lcd_ctrl.v

`timescale 1ns / 1ps

module lcd_ctrl (clk_lcd,
				 sys_rst_n,
				 lcd_rs,
				 lcd_rw,
				 lcd_en,
				 lcd_data
);

input clk_lcd;
input sys_rst_n; //系统复位信号,低电平复位
output lcd_rs; // 0=输入指令,1=输入数据
output lcd_rw; //0=向LCD写入指令或数据,1=从LCD读取信息
output lcd_en; //使能信号,1时读取信息,1→0(下降沿)执行指令
output[7:0] lcd_data; //LCD数据信号

parameter 
CLEAR = 4'd1, //清屏指令
SETFUNCTION = 4'd2, //模式设置指令
SWITCHMODE = 4'd3, //开关控制指令
SETMODE = 4'd4, //设定显示屏或光标移动方向指令
SETDDRAM_1 = 4'd5, //设定第一行DDRAM地址指令
WRITERAM_1 = 4'd6, //向第一行写入的数码
WRITERAM_2 = 4'd7,
IDLE = 4'd8; //空闲

reg [127:0] Data_First = "www.endchina.com"; //液晶显示的第一行的数据
reg [127:0] Data_Second = " chick_kid "; //液晶显示的第二行的数据
reg [127:0] Data_First_Buf,Data_Second_Buf; //液晶显示的数据缓存

//LCD状态机寄存器
reg[3:0] state; //当前状态寄存器
reg lcd_rs_reg = 1'b0; //lcd_rs输出寄存器
reg lcd_rw_reg = 1'b0; //lcd_rw输出寄存器
reg[7:0] lcd_data_reg; //lcd_data输出寄存器
reg lcd_en_sel;
reg [5:0] display_count;

//状态控制
always @ (posedge clk_lcd or negedge sys_rst_n)
if(!sys_rst_n)
	begin
		state <= CLEAR;
		lcd_rs_reg <= 1'b0;
		lcd_data_reg <= 8'b00000000;
		lcd_en_sel <= 1'b1;
		display_count <= 4'b0;
	end
else
	case(state)
		CLEAR:	
				begin
					state <= SETFUNCTION;
					lcd_data_reg <= 8'b00000001;
				end
		SETFUNCTION:
				begin
					state <= SWITCHMODE;
					lcd_data_reg <= 8'b00111000;
				end
		SWITCHMODE:
				begin
					state <= SETMODE;
					lcd_data_reg <= 8'b00001100;
				end
		SETMODE:
				begin
					state <= SETDDRAM_1;
					lcd_data_reg <= 8'b00000110;
				end
		SETDDRAM_1:
				begin
					state <= WRITERAM_1;
					lcd_data_reg <= 8'b10000000; //写入第一行显示起始地址:第一行第二个位置
					Data_First_Buf <= Data_First;
				end
		WRITERAM_1:
				begin
					if(display_count == 6'd16) //display_count等于14时表示第一行数据已写完
						begin
							lcd_data_reg <= 8'b11000000; //送入写第二行的指令
							lcd_rs_reg <= 1'b0;
							display_count <= 4'b0;
							Data_Second_Buf <= Data_Second;
							state <= WRITERAM_2; //写完第一行进入写第二行状态
						end
					else
						begin
							lcd_data_reg <= Data_First_Buf[127:120];
							Data_First_Buf <= (Data_First_Buf << 8);
							lcd_rs_reg <= 1'b1; //RS=1表示写数据
							display_count <= display_count + 1'b1;
							state <= WRITERAM_1;
						end
				end
		WRITERAM_2:
				begin
					if(display_count == 6'd16)
						begin
							lcd_en_sel <= 1'b0;
							lcd_rs_reg <= 1'b0;
							display_count <= 4'b0;
							state <= IDLE; //写完进入空闲状态
						end
					else
						begin
							lcd_data_reg <= Data_Second_Buf[127:120];
							Data_Second_Buf <= (Data_Second_Buf << 8);
							lcd_rs_reg <= 1'b1;
							display_count <= display_count + 1'b1;
							state <= WRITERAM_2;
						end
				end
		IDLE:
				begin
					state <= IDLE;
				end
		default:
				state <= CLEAR;
	endcase

/*
功能设定指令
	指令功能 指令编码 执行时间
	RS R/W DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0 /us
	功能设定 0 0 0 0 1 DL N F X X 40
	功能:设定数据总线位数、显示的行数及字型。参数设定的情况如下:
	位名 设置
	DL 0=数据总线为4位 1=数据总线为8位
	N 0=显示1行 1=显示2行
	F 0=5×7点阵/每字符 1=5×10点阵/每字符

显示开关控制指令
	指令功能 指令编码 执行时间
	RS R/W DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0 /us
	显示开关控制 0 0 0 0 0 0 1 D C B 40
	功能:控制显示器开/关、光标显示/关闭以及光标是否闪烁。参数设定的情况如下:
	位名 设置
	D 0=显示功能关 1=显示功能开
	C 0=无光标 1=有光标
	B 0=光标闪烁 1=光标不闪烁

清屏指令
	指令功能 指令编码 执行时间
	RS R/W DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0 /ms
	清屏 0 0 0 0 0 0 0 0 0 1 1.64
	功能:	<1> 清除液晶显示器,即将DDRAM的内容全部填入"空白"的ASCII码20H;
			<2> 光标归位,即将光标撤回液晶显示屏的左上方;
			<3> 将地址计数器(AC)的值设为0。

设定显示屏或光标移动方向指令
	指令功能 指令编码 执行时间
	RS R/W DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0 /us
	设定显示屏或 0 0 0 0 0 1 S/C R/L X X 40
	光标移动方向
	功能:使光标移位或使整个显示屏幕移位。参数设定的情况如下:
	S/C R/L 设定情况
	0 0 光标左移1格,且AC值减1
	0 1 光标右移1格,且AC值加1
	1 0 显示器上字符全部左移一格,但光标不动
	1 1 显示器上字符全部右移一格,但光标不动

*/

assign lcd_rw = lcd_rw_reg;
assign lcd_rs = lcd_rs_reg;
assign lcd_data = lcd_data_reg;
assign lcd_en = lcd_en_sel ? clk_lcd : 1'b0;

endmodule


 

 

觉得注释的还算详细吧,有什么错误的地方请大家指教,一起学习,嘿嘿

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
FPGA课设中,设计LCD1602滚动显示字符的程序需要考虑以下几个方面的设计思路: 1. 硬件设计: a. 首先需要将FPGA开发板与LCD1602进行连接,包括数据线和控制线。 b. 配置FPGA内部时钟,使其与LCD1602的时钟信号保持同步。 c. 配置FPGA内部IO口,连接到LCD1602的数据线和控制线上。 2. 软件设计: a. 使用硬件描述语言(例如Verilog)编写FPGA的逻辑设计,包括将字符数据存储到FPGA内部存储器中,并将数据信号输出到LCD1602的数据线上。 b. 设计控制信号,包括使LCD1602显示开关有效、写使能有效、光标移位、显示位置等。 c. 编写控制程序,实现字符数据在LCD1602上滚动显示的功能。可以使用计时器产生的时钟信号来控制LCD1602显示的速率,通过改变显示位置来实现滚动效果。通过不断更新数据存储器中的字符数据,可以实现不断滚动显示。 3. 调试与优化: a. 在实际测试中,可能会遇到一些问题,如LCD1602无法正常显示、滚动过程中出现乱码等。可以通过逐步调试的方法,逐一排查问题并解决。 b. 需要注意时序问题,确保FPGA内部的时钟信号与LCD1602的时钟信号完全同步。 c. 在性能优化方面,可以考虑对设计进行优化,减少资源占用,并提高滚动显示的效率和流畅度。 总结:FPGA课设中实现LCD1602滚动显示字符的程序设计思路包括硬件设计和软件设计两方面。在硬件设计上,需要连接FPGA与LCD1602,配置时钟和IO口。在软件设计上,需要编写逻辑设计和控制程序,实现字符数据的滚动显示。最后,在调试与优化过程中,需要解决问题和优化性能,确保程序正常运行且满足要求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值