LCD1602驱动开发记录 顶层模块开发(1)

说明书摘要

指令集

在这里插入图片描述
在这里插入图片描述

目前顶层开发到一半,只开发了写功能,读功能还未开发。另:目前指令逻辑直接在顶层中开发,代码写的比较草,状态机代码没有优化,因此顶层文件代码量超过了300行。。。。。后面可以将指令逻辑做个封装

顶层Verilog代码

//Name:Lcd_1602
//Author:Yang_Cheng_Yu
//Date:2020/4/18
//==================defines=====================
`define SIM
module	lcd1602(
	//================System Signal================
	input				clk,
	input				rst_n,
	//================Interface====================
	output 				RS,
	output 				RW,
	output  			E,
	inout[7:0]			DB,
	input				clr_req,
	input				cur_back_req,
	input				set_input_req,
	input				disp_onoff_req,
	input				shift_req,
	input				set_function_req,
	input				set_char_gen_addr_req,
	input				set_data_save_addr_req,
	input				set_rd_busy_req,
	input				wr_ddram_req,
	input				rd_ddram_req,
	input[7:0]			data_wr
);
	//================parameters===================
	`ifndef SIM
	
	`else
	
	`endif
	//addr
	parameter 	ADDR_CHAR_GEN_REG		= 6'b01_0011;
	parameter	ADDR_DISP_DATA_REG		= 7'b011_0011;
	parameter	ADDR_CNT				= 7'b010_0101;
	//state machine
	localparam	S_IDLE					= 12'b000_0000_00001;
	localparam	S_CLR					= 12'b000_0000_00010;
	localparam	S_CURSOR_BACK			= 12'b000_0000_00100;
	localparam	S_SET_INPUT				= 12'b000_0000_01000;
	localparam	S_DISPLAY_ONOFF			= 12'b000_0000_10000;
	localparam	S_SHIFT					= 12'b000_0001_00000;
	localparam	S_SET_FUNCTION			= 12'b000_0010_00000;
	localparam	S_SET_CHAR_GEN_ADDR		= 12'b000_0100_00000;
	localparam	S_SET_DATA_SAVE_ADDR	= 12'b000_1000_00000;
	localparam	S_RD_BUSY				= 12'b001_0000_00000;
	localparam	S_WR_DDRAM				= 12'b010_0000_00000;
	localparam	S_RD_DDRAM				= 12'b100_0000_00000;
	//command
	localparam	CMD_CLR					= 10'b00_0000_0001;
	localparam	CMD_CURSOR_BACK			= 10'b00_0000_0010;
	localparam	CMD_SET_INPUT			= 10'b00_0000_0110;//默认光标右移
	localparam	CMD_DISPLAY_ONOFF		= 10'b00_0000_1110;//默认开启整体显示,有光标,光标不闪烁
	localparam	CMD_SHIFT				= 10'b00_0001_1100;//默认移动显示文字,向右移动
	localparam	CMD_SET_FUNCTION		= 10'b00_0010_1100;//默认8位总线,双行显示,5*10点阵字符
	localparam	CMD_SET_CHAR_GEN_ADDR	= {4'b0001,ADDR_CHAR_GEN_REG};//前6位是字符发生贮存器地址
	localparam	CMD_SET_DATA_SAVE_ADDR	= {3'b001,ADDR_DISP_DATA_REG};//前7位是数据贮存器地址
	localparam	CMD_RD_BUSY				= {3'b010,ADDR_CNT};//默认不忙
	//================System regs==================
	reg[9:0]	state;
	reg[1:0]	delay;
	wire 		rs;
	wire 		rw;
	reg 		wr_req;
	wire		wr_req_wire;
	assign 		wr_req_wire = wr_req;
	wire		flag_wr_end;
	reg[9:0]	cmd;
	wire[7:0]	out_db;
	assign		out_db = (state==S_RD_BUSY||state==S_RD_DDRAM)?8'hz:cmd[7:0];
	assign		DB=(state==S_RD_DDRAM||state==S_RD_BUSY)?8'hz:out_db;
//	assign		{rs,rw,out_db} = (state!=S_RD_DDRAM)?cmd:10'bz;
	assign 		rs = (state==S_WR_DDRAM||state==S_RD_DDRAM)?1'b1:1'b0;
	assign 		rw = (state==S_RD_BUSY||state==S_RD_DDRAM)?1'b1:1'b0;
	wire[9:0]	CMD_WR_DDRAM;
	wire[9:0]	CMD_RD_DDRAM;
	assign		CMD_WR_DDRAM = {2'b10,data_wr};
	assign		CMD_RD_DDRAM = {2'b11,8'hz};

	//================Main Codes===================
lcd_write lcd_write_inst(
	//================System Signal================
	.clk			(clk),
	.rst_n			(rst_n),
	//================Interface====================
	.rs_in			(rs),
	.RS				(RS),//指令数据选择
	.RW				(RW),
	.E				(E),
	.DB				(DB),
	.wr_req			(wr_req_wire),
	.data			(out_db),
	.flag_wr_end	(flag_wr_end)
);
	//state machine
	always	@(posedge clk or negedge rst_n)begin
		if(rst_n==1'b0)
			state <= S_IDLE;
		else case(state)
			S_IDLE:begin
				if(clr_req==1'b1)
					state <= S_CLR;
				else
					state <= S_IDLE;
			end
			S_CLR:begin
				if(flag_wr_end==1'b1)
					state <= S_IDLE;
				else
					state <= S_CLR;
			end
			S_CURSOR_BACK:begin
				if(flag_wr_end==1'b1)
					state <= S_IDLE;
				else
					state <= S_CURSOR_BACK;
			end
			S_SET_INPUT:begin
				if(flag_wr_end==1'b1)
					state <= S_IDLE;
				else
					state <= S_SET_INPUT;
			end
			S_DISPLAY_ONOFF:begin
				if(flag_wr_end==1'b1)
					state <= S_IDLE;
				else
					state <= S_DISPLAY_ONOFF;
			end
			S_SHIFT:begin
				if(flag_wr_end==1'b1)
					state <= S_IDLE;
				else
					state <= S_SHIFT;
			end
			S_SET_FUNCTION:begin
				if(flag_wr_end==1'b1)
					state <= S_IDLE;
				else
					state <= S_SET_FUNCTION;
			end
			S_SET_CHAR_GEN_ADDR:begin
				if(flag_wr_end==1'b1)
					state <= S_IDLE;
				else
					state <= S_SET_CHAR_GEN_ADDR;
			end
			S_SET_DATA_SAVE_ADDR:begin
				if(flag_wr_end==1'b1)
					state <= S_IDLE;
				else
					state <= S_SET_DATA_SAVE_ADDR;
			end
//			S_RD_BUSY:begin
//				if(flag_wr_end==1'b1)
//					state <= S_IDLE;
//				else
//					state <= S_RD_BUSY;
//			end
			S_WR_DDRAM:begin
				if(flag_wr_end==1'b1)
					state <= S_IDLE;
				else
					state <= S_WR_DDRAM;
			end
//			S_RD_DDRAM:begin
				
//			end
			default:state <= S_IDLE;
		endcase
	end
	//cmd
	always	@(posedge clk or negedge rst_n)begin
		if(rst_n==1'b0)
			state <= S_IDLE;
		else case(state)
			S_IDLE:begin
				cmd <= 10'b00_0000_0000;
			end
			S_CLR:begin
				cmd <= CMD_CLR;
				if(delay==2'd2)
					delay <= 'd0;
				else
					delay <= delay + 1'b1;
				if(delay==2'd1)
					wr_req <= 1'b1;
				else if(delay==2'd2)
					wr_req <= 1'b0;
			end
			S_CURSOR_BACK:begin
				cmd <= CMD_CURSOR_BACK;
				if(delay==2'd2)
					delay <= 'd0;
				else
					delay <= delay + 1'b1;
				if(delay==2'd1)
					wr_req <= 1'b1;
				else if(delay==2'd2)
					wr_req <= 1'b0;
			end
			S_SET_INPUT:begin
				cmd <= CMD_SET_INPUT;
				if(delay==2'd2)
					delay <= 'd0;
				else
					delay <= delay + 1'b1;
				if(delay==2'd1)
					wr_req <= 1'b1;
				else if(delay==2'd2)
					wr_req <= 1'b0;
			end
			S_DISPLAY_ONOFF:begin
				cmd <= CMD_DISPLAY_ONOFF;
				if(delay==2'd2)
					delay <= 'd0;
				else
					delay <= delay + 1'b1;
				if(delay==2'd1)
					wr_req <= 1'b1;
				else if(delay==2'd2)
					wr_req <= 1'b0;				
			end
			S_SHIFT:begin
				cmd <= CMD_SHIFT;
				if(delay==2'd2)
					delay <= 'd0;
				else
					delay <= delay + 1'b1;
				if(delay==2'd1)
					wr_req <= 1'b1;
				else if(delay==2'd2)
					wr_req <= 1'b0;				
			end
			S_SET_FUNCTION:begin
				cmd <= CMD_SET_FUNCTION;
				if(delay==2'd2)
					delay <= 'd0;
				else
					delay <= delay + 1'b1;
				if(delay==2'd1)
					wr_req <= 1'b1;
				else if(delay==2'd2)
					wr_req <= 1'b0;
			end
			S_SET_CHAR_GEN_ADDR:begin
				cmd <= CMD_SET_CHAR_GEN_ADDR;
				if(delay==2'd2)
					delay <= 'd0;
				else
					delay <= delay + 1'b1;
				if(delay==2'd1)
					wr_req <= 1'b1;
				else if(delay==2'd2)
					wr_req <= 1'b0;
			end
			S_SET_DATA_SAVE_ADDR:begin
				cmd <= CMD_SET_DATA_SAVE_ADDR;
				if(delay==2'd2)
					delay <= 'd0;
				else
					delay <= delay + 1'b1;
				if(delay==2'd1)
					wr_req <= 1'b1;
				else if(delay==2'd2)
					wr_req <= 1'b0;
			end
			S_RD_BUSY:begin
				cmd <= CMD_RD_BUSY;
				if(delay==2'd2)
					delay <= 'd0;
				else
					delay <= delay + 1'b1;
				if(delay==2'd1)
					wr_req <= 1'b1;
				else if(delay==2'd2)
					wr_req <= 1'b0;
			end
			S_WR_DDRAM:begin
				cmd <= CMD_WR_DDRAM;
				if(delay==2'd2)
					delay <= 'd0;
				else
					delay <= delay + 1'b1;
				if(delay==2'd1)
					wr_req <= 1'b1;
				else if(delay==2'd2)
					wr_req <= 1'b0;
			end
//			S_RD_DDRAM:begin
				
//			end
			default:begin
				cmd <= 10'b00_0000_0000;
				delay <= 'd0;
			end
		endcase
	end	
endmodule

发布了18 篇原创文章 · 获赞 25 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_43650722/article/details/105605713