/**
******************************************************************************
* @file LCD_con_v6.v
* @author 西殿源
* @version V6
* @date 07/19/2012
* @brief LCD1602控制模块
* @info 1. 状态机分段,
2. 配置变量整合为寄存器组,没找到可以整合的部分
******************************************************************************
*/
module LCD_con_v6(
input[7:0] data_in,
input rst_n,
input clk,
input wr,
output reg[1:0] RSW_O,//RS RW
output reg[7:0] PORT_O,//DATA
output e,
output reg work_clk
);
parameter cwr =2'b00;
parameter dwr =2'b10;
parameter no=0;
parameter yes=1;
parameter FREE =3'd0;// 10'bz;//空闲状态总线高阻 1
parameter CLR =3'd1;// 10'b1;//清屏 2
parameter HOME =3'd2;// 10'b10;//光标归位 3
parameter CURSOR =3'd3;// 10'b110;//显示效果设置 4
parameter DISPLA =3'd4;// 10'b1100;//显示开关 5
parameter SETMOD =3'd5;// 10'b111100;//总线模式设置 6
parameter LOCAT =3'd6;// 10'b10000000;//显示位置 7
parameter WRDAT =3'd7;//
reg[7:0] data_temp;
reg[7:0] display_cnt;//字符显示个数计数器
reg[2:0] state;
reg[2:0] state_next;
reg[15:0] temp_fp;
reg[1:0] rsw;
reg[7:0] data_lcd;
reg lcd_exe_t;//用在时序逻辑
reg lcd_exe;//当前是否有指令或数据操作,用在组合逻辑
always @(posedge clk,negedge rst_n) begin
if(!rst_n) begin
temp_fp<=0;
work_clk<=no;
end
else if(temp_fp==999) begin
temp_fp<=0;
work_clk<=yes;
end
else begin
temp_fp<=temp_fp+1;
work_clk<=no;
end
end
assign e=((lcd_exe_t==yes)&&(temp_fp==2))? 1:0;//根据条件使能lcd操作时钟
always @(posedge clk,negedge rst_n) begin
if(!rst_n) begin
state<=SETMOD;//初始化状态为设置模式
display_cnt<=0;//字符显示个数计数器
RSW_O<=0;
PORT_O<=0;
lcd_exe_t<=no;
end
else if(wr) begin//每个clk的上升沿检测是否有数据写入请求
state<=WRDAT;//跳到写数据状态
data_temp<=data_in;//将输入数据读入寄存器
end
else if(work_clk==yes) begin//lcd内部操作时钟,此乃使能时钟,可避免混杂的时钟漫天飞
RSW_O<=rsw;//同步输出
PORT_O<=data_lcd;//同步输出
lcd_exe_t<=lcd_exe;//同步输出
state<=state_next;//状态跳转
end
end
always @(state) begin
case(state)
//////////////////////////////////////////////////////////////////
FREE:
begin
// rsw<=0;//滥竽充数,删去也无妨
// data_lcd<=8'd0;//滥竽充数,删去也无妨
lcd_exe=no;
state_next=FREE;//就在这闲逛兜圈吧吧
end
CLR:
begin
rsw=cwr;//写指令控制
data_lcd=8'h1;//写指令操作码
lcd_exe=yes;
state_next=LOCAT;
end
HOME:
begin
rsw=cwr;//写指令控制
data_lcd=8'h2;//写指令操作码
lcd_exe=yes;
state_next=CLR;
end
CURSOR:
begin
rsw=cwr;//写指令控制
data_lcd=8'h6;//写指令操作码
lcd_exe=yes;
state_next=CLR;
end
DISPLA:
begin
rsw=cwr;//写指令控制
data_lcd=8'hF;//写指令操作码
lcd_exe=yes;
state_next=CURSOR;
end
SETMOD:
begin
rsw=cwr;//写指令控制
data_lcd=8'h3C;//写指令操作码
lcd_exe=yes;
state_next=DISPLA;
end
LOCAT:
begin
rsw=cwr;//写指令控制
data_lcd=8'h80;//写指令操作码
lcd_exe=yes;
state_next=FREE;
end
WRDAT:
begin
rsw=dwr;//写数据控制
data_lcd=data_temp;//写数据
lcd_exe=yes;
state_next=FREE;
end
//////////////////////////////////////////////////////////////////////////////////////////
default : state_next= SETMOD;
endcase//state
end//always
endmodule
文章评论(0条评论)
登录后参与讨论