LCD1602驱动开发记录 顶层模块开发(1)
发布日期:2021-05-07 22:56:19 浏览次数:20 分类:原创文章

本文共 6869 字,大约阅读时间需要 22 分钟。

说明书摘要


指令集


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


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


顶层Verilog代码


//Name:Lcd_1602//Author:Yang_Cheng_Yu//Date:2020/4/18//==================defines=====================`define SIMmodule	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
上一篇:SPI主机的Verilog代码及验证(优化版)
下一篇:LCD1602液晶屏的FPGA驱动(1)————读,写模块

发表评论

最新留言

路过,博主的博客真漂亮。。
[***.116.15.85]2025年03月19日 16时42分48秒