【毕业设计】42-基于FPGA的LCD1602控制器设计仿真与实现(原理图+仿真+源代码+论文)

【毕业设计】42基于FPGA的LCD1602控制器设计仿真与实现(原理图+仿真+源代码+论文)

文章目录

  • 【毕业设计】42基于FPGA的LCD1602控制器设计仿真与实现(原理图+仿真+源代码+论文)
    • 资料下载链接
    • 任务书
    • 设计说明书
      • 摘要
      • 设计框架架构
      • 设计说明书及设计文件
      • 源码展示

资料下载链接

资料下载链接
资料链接:https://www.cirmall.com/circuit/29938/
包含此题目毕业设计全套资料:
原理图工程文件
仿真工程文件
源代码
仿真截图
低重复率论文,字数:19964

任务书

基于altera 公司cyclone4代芯片的fpga以及quartusII软件设计一款屏幕显示系统,显示装置可以选择点阵或字符型液晶,最终实现滚动显示、可控制滚动方向、暂停、清屏等功能。

设计说明书

摘要

本次系统为基于FPGA的显示控制器设计,实现液晶显示器的左翻滚、右翻滚、暂停、清屏的功能。程序编写对各个功能编写程序。系统具有多功能,通过模块化的方式来进行设计,根据各个功能进行编程,在设计上和仿真上均通过模块化的方式进行,保证设计可以减少调试时间,更可以使功能顺利实现。本次系统由于考虑多方面的因素实现了显示控制器设计,具有一定的推广意义和学习意义。
该控制器可以显示字符、图片两个部分。字符显示功能上通过调用RAM实现,可以通过调用液晶显示器内部的字库来实现字符的调用。功能按键实时控制液晶显示器的状态,同步改变LCD上显示的内容,并且将内部RAM的字符图片数据显示在LCD1602显示器中。
本次毕业设计使用FPGA系列产品开发,并且使用到了当前市面上常用的LCD1602液晶显示器。使用FPGA开发系统可以缩短研发系统的开发时间。并且系统分两个模块按键、与液晶显示模块。模块化的设计可以使其应用在更多FPGA系列产品上。基于FPGA的显示控制器设计是当前热门研究方式,具有人机交互意义并且可以使人们生活出现新的改变。

设计框架架构

【毕业设计】42-基于FPGA的LCD1602控制器设计仿真与实现(原理图+仿真+源代码+论文)_第1张图片

第一章 绪论 1
1.1 研究背景与意义 1
1.2 课题发展现状 1
1.3 国内外发展情况 1
1.31 国外发展情况 2
1.32 国内发展情况 2
1.4 EDA技术的设计流程 2
第二章 系统设计平台及方案 4
2.1 EDA技术发展 4
2.2 FPGA介绍 6
2.21 FPGA工作原理 6
2.22 FPGA基本特点 7
2.3 Quartus II简编程软件的介绍 8
2.31 Quartus II简介 8
2.32 Quartus II设计流程 8
2.4 编程语言介绍 9
2.5 系统设计方案 10
2.51 系统实现功能描述 10
2.52 系统功能框架 11
第三章 系统硬件设计 13
3.1 FPGA最小系统设计 13
3.11 电源电路 13
3.12 晶振电路 14
3.13 复位电路 15
3.14 EPCS4SI8配置芯片电路 15
3.15 下载接口电路 16
3.2 LCD1602电路设计 16
3.3 按键电路设计 19
3.4 系统总电路设计 19
3.5 系统PCB设计 20
第四章 系统软件设计及仿真 22
4.1 系统软件设计 22
4.12 LCD1602控制模块设计 22
4.13 按键模块软件设计 26
4.14 顶层模块设计 28
4.2 系统仿真验证 29
4.21 仿真流程 29
4.22 仿真结果 31
结 论 35
参考文献 37
致 谢 38
附录 39
外文资料原文 50
译文 53

设计说明书及设计文件

【毕业设计】42-基于FPGA的LCD1602控制器设计仿真与实现(原理图+仿真+源代码+论文)_第2张图片字数:19964

源码展示

源代码:
library verilog;
use verilog.vl_types.all;
entity lcd1602 is
    port(
        clk             : in     vl_logic;
        rst_n           : in     vl_logic;
        key1            : in     vl_logic;
        key2            : in     vl_logic;
        key3            : in     vl_logic;
        key4            : in     vl_logic;
        lcd_rs          : out    vl_logic;
        lcd_rw          : out    vl_logic;
        lcd_en          : out    vl_logic;
        lcd_data        : out    vl_logic_vector(7 downto 0)
    );
end lcd1602;
library verilog;
use verilog.vl_types.all;
entity key_bounce is
    port(
        key_in          : in     vl_logic_vector(3 downto 0);
        clk             : in     vl_logic;
        rst_n           : in     vl_logic;
        key1            : out    vl_logic;
        key2            : out    vl_logic;
        key3            : out    vl_logic;
        key4            : out    vl_logic
    );
end key_bounce;
library verilog;
use verilog.vl_types.all;
entity top is
    port(
        clk             : in     vl_logic;
        rst_n           : in     vl_logic;
        key_in          : in     vl_logic_vector(3 downto 0);
        lcd_rs          : out    vl_logic;
        lcd_rw          : out    vl_logic;
        lcd_en          : out    vl_logic;
        lcd_data        : out    vl_logic_vector(7 downto 0)
    );
end top;
module lcd1602(
	input				clk			,
	input				rst_n		,
	input				key1		,//左滚动
	input				key2		,//右滚动
	input				key3		,//暂停
	input				key4		,//清屏
	output	reg			lcd_rs		,//0:命令 1:数据
	output			    lcd_rw		,//0:写  1:读
	output	reg			lcd_en		,//使能
	output	reg	[7:0]	lcd_data	 //8-bit 
	);
assign 				lcd_rw = 1'b0		;  //只写
reg	[4:0]			char_cnt			;
reg	[7:0]			data_display1 =8'b0	; //第一行数据
reg	[7:0]			data_display2 =8'b0	; //第二行数据
localparam	S0			= 4'd0	;
localparam	S1			= 4'd1	;
localparam	S2			= 4'd2	;
localparam	S3			= 4'd3	;
localparam	S4			= 4'd4	;
localparam	S5			= 4'd5	;
localparam	S6			= 4'd6	;
localparam	S7			= 4'd7	;
localparam	S8			= 4'd8	;
localparam	IDLE		= 4'd9	;
localparam	LEFT		= 4'd10	;
localparam	RIGHT		= 4'd11	;
localparam	STOP		= 4'd12	;
localparam	CLEAR		= 4'd13	;
//localparam	cnt_2ms		= 17'd50000		;
 // 2ms 时钟计数
//localparam	cnt_15ms	= 17'd7			;
 // 16ms延时
//localparam	cnt_500ms	= 17'd249		;
 // 500ms延时
localparam	cnt_2ms		= 17'd500	;
 // 缩短仿真计数2ms 时钟
localparam	cnt_15ms	= 17'd7;	
// 缩短仿真计数16ms延时
localparam	cnt_500ms	= 17'd9	;
 // 缩短仿真计数500ms延时	
reg	[16:0]			cnt_en			;
always @(posedge clk or negedge rst_n) 
	if (!rst_n) 
		cnt_en <= 17'd0;
	else if (cnt_en==cnt_2ms - 1) 
		cnt_en <= 17'd0;
	else 
		cnt_en <= cnt_en + 1'b1;
//**************************************************************		
reg		[1:0]	key1_reg			; 
//同步key1 ,左滚动
reg		[1:0]	key2_reg			;
 //同步key2 ,右滚动
reg		[1:0]	key3_reg			;
 //同步key3 ,暂停
reg		[1:0]	key4_reg			;
 //同步key4 ,清屏
wire [3:0] 			key ;
assign key ={key4_reg[1],key3_reg[1],key2_reg[1],key1_reg[1]};
	always @(posedge lcd_en or negedge rst_n) 
	if (!rst_n)begin 
		key1_reg <= 2'b11;
		key2_reg <= 2'b11;
		key3_reg <= 2'b11;
		key4_reg <= 3'b111;
	end
	else begin 
		key1_reg <= {key1_reg[0],	key1};
		key2_reg <= {key2_reg[0],	key2};
		key3_reg <= {key3_reg[0],	key3};
		key4_reg <= {key4_reg[0], 	key4};
	end                     
//**********************************************	
always @(posedge clk or negedge rst_n) //lcd_en为500khz
	if (!rst_n) 
		lcd_en <= 1'b0;
	else if (cnt_en==cnt_2ms - 1) 
		lcd_en <= ~lcd_en;
reg [3:0] 		state;
reg [31:0] 		cnt;
always @(posedge lcd_en or negedge rst_n)
begin
	if(!rst_n)begin
		cnt			<=  1'b0;
		lcd_rs		<=	1'b0;
		lcd_data	<=	1'b0;
		state		<= 	S0;
		char_cnt	<= 	4'd0;
	end
	else case(state)
		S0:begin	
					lcd_rs		<=	1'b0;           //15ms延时
				if(cnt==cnt_15ms) begin
					cnt			<=  10'b0;
					state		<= 	S1;
				end
				else begin
					cnt			<=  cnt+1'b1;
					state		<= 	state;
				end
			end	
		S1:begin
				lcd_rs		<=	1'b0;
 //功能设定,数据8位,显示2行,5x7点阵
				lcd_data	<=	8'b0011_1000;
				state		<= 	S2;
			end
		S2:begin
				lcd_rs		<=	1'b0;
 /显示开关控制,一直显示,无光标。
				lcd_data	<=	8'b0000_1100;   //8'b0000_1ABC;
A:显示功能;0关1开。
				state		<= 	S3;			/
/B:光标;	0无1有。	
			end									
//C:光标闪 ; 0闪1不闪。
		S3:begin
				lcd_rs		<=	1'b0; 
//清屏,指令码01h
				lcd_data	<=	8'h01;
				state		<= 	S4;
			end
		S4:begin
				lcd_rs		<=	1'b0;
//设置模式,写入一个数据,光标右移
				lcd_data	<=	8'b0000_0101;
//8'b0000_01DS;	DS: 00光标左移,10光标右移
				state		<= 	S5;	
//10显示屏不移动,11显示屏右移 
			end 
		S5:begin
				lcd_rs		<=	1'b0; 
//设置第一行地址
				lcd_data	<=	8'b10000000;
高位
				state		<= 	S6;
			end
		S6:begin
				lcd_rs		<=	1'b1;
//写入第一行数据
				lcd_data	<=	data_display1;
				char_cnt	<=  char_cnt+1'b1;
				if(char_cnt==5'd15)begin
					state	<= 	S7;
				end
				else 
					state	<= 	state;
			end
		S7:begin
				lcd_rs		<=	1'b0;
//设置第二行地址
				lcd_data	<=	8'b11000000;
				state		<= 	S8;
			end	
		S8:begin
				lcd_rs		<=	1'b1;
//写入第二行数据
				lcd_data	<=	data_display2;
				char_cnt	<=  char_cnt+1'b1;
				if(char_cnt==5'd31)begin
					state		<= 	IDLE;
					char_cnt	<=  5'd0;
				end   
				else 
					state		<= 	S8;	
			end	
****************以上都是初始****************************//
		IDLE:begin
				lcd_rs	<=	1'b0;    
				cnt		<=  0;
				lcd_data<=	8'b0;
				begin
				case(key)
					4'b1110:state	<=	LEFT    ;
					4'b1101:state	<=	RIGHT   ;
					4'b1011:state	<=	STOP    ;
					4'b0111:state	<=	CLEAR    ;
				default: state	<=	IDLE;
				endcase
				end
			end
		LEFT:begin 
					lcd_rs		<=	1'b0; 
				begin
					case(key)
					4'b1110:state	<=	LEFT    ;
					4'b1101:state	<=	RIGHT   ;
					4'b1011:state	<=	STOP    ;
					4'b0111:state	<=	CLEAR   ;
					default: state	<=	LEFT	;
					endcase
//左滚动,0.5s移动一次。
				end
//设置显示屏或光标移动方向,
				begin
					if(cnt==1)                                  //8'b0001_AB00;	    AB: 00光标左移,01光标右移;   
						lcd_data	<=	8'b0001_1000;           
//10显示屏左移,11显示屏右移 ;   
					else
						lcd_data	<=	8'h0;
				end
				begin
					if(cnt==cnt_500ms)	
						cnt			<=  0;
					else
						cnt<=cnt+1'b1;
				end
			end		
		RIGHT:begin 
					lcd_rs			<=	1'b0; 
				begin
					case(key)								
//右滚动,0.5s移动一次。
						4'b1110:state	<=	LEFT    ;
//设置显示屏或光标移动方向,
						4'b1101:state	<=	RIGHT   ;
 //8'b0001_AB00;	    AB: 00光标左移,01光标右移;   
						4'b1011:state	<=	STOP    ;       
//10显示屏左移,11显示屏右移 ; 
						4'b0111:state	<=	CLEAR    ;
					default: 	state	<=	RIGHT;
					endcase	
				end
				begin
					if(cnt==1)
						lcd_data	<=	8'b0001_1100;	
					else
						lcd_data	<=	8'h0;
				end
				begin
					if(cnt==cnt_500ms)	   	
						cnt			<=  0;
					else
						cnt<=cnt+1'b1;
				end
			end
		STOP:begin 
//暂停
				cnt		<=  32'b0;
				lcd_data<=	8'b0;
				lcd_rs  <=  1'b0;
				case(key)
					4'b1110:state	<=	LEFT    ;
					4'b1101:state	<=	RIGHT   ;
					4'b1011:state	<=	STOP    ;
					4'b0111:state	<=	CLEAR    ;
				default: state	<=	STOP;
				endcase
			end
		CLEAR:begin
//清屏
				cnt		<=  32'b0; 
				lcd_rs  <=  1'b0;
				lcd_data<=	8'h01;
				case(key)
					4'b1110:state	<=	LEFT    ;
					4'b1101:state	<=	RIGHT   ;
					4'b1011:state	<=	STOP    ;
					4'b0111:state	<=	CLEAR    ;
				default: 	state	<=	CLEAR;
				endcase
			end
		default:state <= 4'd0;
		endcase
end
always @(*) begin
//第一行数据显示“hello chengdu”
	case(char_cnt)
		5'd0: data_display1   = "h";
		5'd1: data_display1   = "e";
		5'd2: data_display1   = "l";
		5'd3: data_display1   = "l";
		5'd4: data_display1   = "o";
		5'd5: data_display1   = " ";
		5'd6: data_display1   = "c";
		5'd7: data_display1   = "h";
		5'd8: data_display1   = "e";
		5'd9: data_display1   = "n";
		5'd10: data_display1  = "g";
		5'd11: data_display1  = "d";
		5'd12: data_display1  = "u";
		5'd13: data_display1  = "-";
		5'd14: data_display1  = "-";
		5'd15: data_display1  = "-";
//第二行数据显示“---2021-03-15---”
		5'd16: data_display2  = "-";
		5'd17: data_display2  = "-";
		5'd18: data_display2  = "-";
		5'd19: data_display2  = "-";
		5'd20: data_display2  = "2";
		5'd21: data_display2  = "0";
		5'd22: data_display2  = "2";
		5'd23: data_display2  = "1";
		5'd24: data_display2  = "-";
		5'd25: data_display2  = "0";
		5'd26: data_display2  = "3";
		5'd27: data_display2  = "-";
		5'd28: data_display2  = "1";
		5'd29: data_display2  = "5";
		5'd30: data_display2  = "-";
		5'd31: data_display2  = "-";
		default:begin
				data_display1 = "-";
				data_display2 = "-";
				end
	endcase
end
endmodule

你可能感兴趣的:(fpga开发)