欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2024-02-22 21:38:28
...

说明书摘要

指令集

LCD1602驱动开发记录 顶层模块开发(1)
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