基于Verilog HDL的FPGA程序(智能洗衣机)


2023年12月20日发(作者:spicy英语发音)

华中科技大学

电子线路课程设计

题 目:智能洗衣

院 系:控制科学与工程系

班 级:自动化100X班

姓 名:

:fanjunchao1991@

指导老师:

目录

一 题目分析。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。1

二 系统流程图.。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。2

三 主要模块介绍.。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。5

四 各按键功能.。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。6

五 仿真波形.。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。7

六 实验总结。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。8

七 附录。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。9

一:题目分析

本次课程设计要求以Verilog HDL硬件描述语言为基础,以DE2开发板为工具,编写智能洗衣机的模拟程序。

首先,我在熟悉题目要求的前提下,将题目要求划分为以下几个小的项目,每个项目尽量用单独的模块实现其功能:

① 洗衣过程的转换:控制洗衣过程在每个过程对应的状态机之间

转换,用control.v模块实现。

② 洗衣时间的显示:通过直接调用上学期编写的24小时智能时钟程序的计时模块,并用总时间减去已用时间得到剩余时间,用led_show.v实现。

本程序的特:

①led灯表示水位: 通过一定的算法,实现用led灯的亮灭表示水位。Led依次点亮表示注水过程,相反,表示排水和甩干过程。

②1602 LCD液晶屏: 用LCD显示所有操作步骤和过程,包括选择模式,当前洗衣模式和状态,洗衣完毕等。这些过程都是用LCD液晶屏具体显示。

③按键使用和去抖: 因为要使用按键进行模式的选择,所以我用软件去抖的方式实现按键按动时的去抖。

1

④暂停键模拟断电保护:设计了一个暂停键,模拟真实情况中的断电保护。当暂停时模拟现实中的断电;暂停结束模拟现实中的重新上电,程序从断点继续运行。

二:系统流程图

2

MODE 1 OR MODE 2 OR MODE 3:

Inject

(注水))

NO

是否已经洗过衣服?

YES

Wash

(洗衣)

Potch

(漂洗)

Drain

(排水)

Dry

(甩干)

洗衣完毕?

3

N

Y

MODE 4

4

Inject

(注水)

Potch

(漂洗)

Drain

(排水)

Dry

(甩干)

洗衣完毕?

N

Y

Wash over

MODE 5

流程图说明:第一个为总的控制系统的流程图,后面三个为总流程图中,每种模式的详细流程图。

Wash over

Dry

(甩干)

三:主要模块介绍

module my_start: 顶层模块,调用下层模块。

module HZ_1: 分频模块,通过10分频和5分频将50Mhz

分频成为1hz。

module control: 控制模块,控制洗衣模式状态机的转换。

module led_show: 倒计时模块,通过减去已用时间,得到剩余时间。

module put_bottom:软件去抖模块,通过软件去抖,检测按键按动情况。

module lcd_show: 1602液晶屏显示模块,包括驱动和需要显示的字符。

Module water_station:用led灯显示当前水位。

5

四:各按键功能

SW_0 :电源键,‘0’时表示power off(未开电源),‘1’表示洗衣机已经开机,处于工作状态,优先级最高。

SW_1 :暂停键,‘0’时表示正常工作,‘1’时表示暂停工作, 处于待机状态。

Key_2

Key_1

液晶屏

数码管

Led:

:确定键,按下表示模式选择确定,进入洗衣工作状态。

:模式选择键,洗衣机共有5种工作模式,用此键进行选择模式。

:显示洗衣机工作状态。

:显示洗衣机当前工作模式剩余时间和整个工作状态剩余时间。

Hex7,hex6:表示当前状态剩余分钟。

Hex5,hex4:表示剩余时间(秒)。

Hex1,hex0:表示整个状态剩余时间。

表示洗衣机水位状态,水位越高,led灯亮的越多。

6

五:仿真波形

说明:bot_1为模式选择按键,bot_2为确认按键,当57us按动确认键后,进入所选择的的mode 1。wsh_sty为当前洗衣状态,0代表注水,1代表洗衣(为了缩短仿真时间,我将洗衣时间改成一分钟),2代表排水,3代表甩干,4代表漂洗。可以看到,洗衣过程如下:0-1-2-3---0-4-2-3---0-4-2-3---wash over。符合要求,下载到开发板上以后也验证成功,mode 2和mode 3是类似状态,不再累述。

7

说明:这是mode 4的仿真图,wsh_sty中0代表注水,2代表排水,3代表甩干,4代表漂洗。可以看到,洗衣方式为0-4-2-3--0-4-2-3--wash over,符合题目要求。

实验总结

在去年多功能时钟的基础上,今年的课程设计让我学会了很多的新知识,也少走了很多弯路。

①模块化设计的思想:本次课程设计使用了很多去年设计多功能时钟的模块,编写可移植模块,对程序编写有莫大的好处。

②学习到很多小的注意事项:以前编写程序,从来不管warning,但是本次课设,本着严格要求的态度,我把所有warning8

都详细baidu和修改了一遍,最终将两百多个warning减少到了15个。通过修改warning,可以发现并改正很多不良习惯。

我的200多个警告里面大部分是因为无意识的疏忽造成的。比如,time_flag <= time_flag + 1;其中time_flag为11位寄存器型变量,编译时提示的警告为‘1’没有标明位数,被默认设置成为32位,所以改成 11'b1即可消除警告,这种重复性错误占有很大比例。

再比如,case语句没有养成加defaulet的习惯,我认为虽然运行时似乎对程序没有影响,但是遇到干扰或者时序混乱等情况时可能会出现问题。

还有比如,写代码时,在模块名后面的输入输出变量声明时多写了一个逗号等。

这些都提醒自己在写代码时不能投机取巧,尽管不会产生错误,但却可能造成以后写Verilog时习惯性疏忽。

但是也有一些警告需要我上网查才能知道是什么意思,比如quartus软件里可以自己设定时钟频率,比如为输入输出引脚分配电容等。

③ 体的构思和准备:我在写代码之前,构思了洗衣机的操作流程和可能遇到的问题,解决方案等。将准备工作做充足以后,写代码就会很快,遇到的错误也更少。

9

附录:(完整代码)

module my_start(

input key_0,key_1,

input cp_50,

input bot_1,bot_2,

output LCD_EN,

output LCD_RS,

output LCD_RW,

output LCD_ON,

output LCD_BLON,

output[7:0] LCD_DATA,

output [6:0] led_min0,led_min1,led_sec0, led_sec1,min_all1,min_all2,

output[0:14] led_wt

);

reg [2:0]mode;

initial mode=3'b000;

wire [2:0] wsh_sty;

wire [2:0] mode_slt;

wire cp_1,mode_change,bot_2t;

HZ_1 h_1(cp_50,1,cp_1);

control con_1( key_1,mode,cp_1,cp_50,wsh_sty, mode_change,led_min0,led_min1,led_sec0,

always

begin

end

put_bottom put_1(cp_50,bot_1,bot_2,mode,bot_2t,mode_slt);

lcd_show lcd(

.CLOCK_50(cp_50),

.RST_N(1),

.mode(mode),

.mode_slt(mode_slt),

.wsh_sty(wsh_sty),

.LCD_DATA(LCD_DATA),

.LCD_EN(LCD_EN),

.LCD_RS(LCD_RS),

.LCD_RW(LCD_RW),

10

if((key_0==1)&&(mode==3'b000)) mode<=3'b110;

else if(key_0==0)

mode<=3'b000;

mode<=3'b111;

mode<=mode_slt;

if(mode_change==1)

@ (posedge cp_50)

led_sec1,min_all1,min_all2,led_wt);

if((mode==3'b110)&&(bot_2t==0))

.LCD_ON(LCD_ON),

.LCD_BLON(LCD_BLON)

);

Endmodule

module put_bottom(cp_50,bot_1,bot_2,mode,bot_2t,mode_slt);//去抖时间20ms,检测时间20um,没有按是1

input cp_50,bot_1,bot_2;

input[2:0]mode;

output bot_2t;

output[2:0]mode_slt;

reg bot_1f,bot_1t,bot_2f,bot_2t;

reg [2:0]mode_slt;

reg [10:0]flag_1,flag_2;

initial

begin

end

bot_1f

bot_2f

bot_1t

bot_2t

<=

<=

<=

<=

1;

1;

1;

1;

mode_slt<=3'b001;

wire [3:0]q_0,q_1,q_2;

wire Q_0,Q_1,cp_u;

counter_10 u1 (1,cp_50,q_0[3:0],Q_0);

counter_10 u2 (1,Q_0,q_1[3:0],Q_1);

counter_10 u3 (1,Q_1,q_2[3:0],cp_u);//20微秒

always @ (posedge cp_u)

begin

if(bot_1f==bot_1)

else

if(bot_2f==bot_2)

flag_2 <= flag_2+11'b1;

11

begin

end

>11'd2000)

flag_1<=0;

bot_1t<=bot_1f;

begin

flag_1

bot_1f

<= 0;

<=bot_1;

flag_1 <= flag_1+11'b1;

if(flag_1

end

end

@

else

begin

end

>11'd2000)

flag_2<=0;

bot_2t<=bot_2f;

begin

flag_2

bot_2f

<= 0;

<=bot_2;

if(flag_2

end

always

end

( posedge bot_1t )

begin

if((mode==3'b110)&&(mode_slt<3'b101))

mode_slt <= mode_slt + 3'b001;

mode_slt <= 3'b001;

else if((mode==3'b110)&&(mode_slt>3'b100))

endmodule

module water_station(key_1,led_sec0,cp_1,wsh_sty,mode,time_flag,led_wt);

input [2:0]wsh_sty,mode;

input [10:0] time_flag;

input cp_1,key_1;

input[7:0] led_sec0;

output[0:14] led_wt;

reg [0:14] led_wt;

always @ (posedge cp_1)

begin

if((~(key_1==0))&&(mode!=3'b000))

else

case(mode)

3'b001,

3'b010,

3'b011,

3'b100:

12

begin

end

if((wsh_sty==3'b001)||(wsh_sty==3'b100))

else

led_wt <= led_wt;

led_wt <= 0;

1) + 1'b1;

1);

end

begin

end

begin

end

led_wt <= 15'b0;

if(time_flag==0)

led_wt <= 15'h00ff;

led_wt <= (led_wt >> 1);

else if(time_flag[2:0]==3'b000)

case(wsh_sty)

3'b000:

3'b001:

3'b010:

led_wt <= (led_wt >> 1);

end

if(time_flag[4:0]==3'b00000)led_wt <= (led_wt >>

if(time_flag[1:0]==2'b00)

led_wt <= ~led_wt;

led_wt <= 15'h7fff ;

led_wt <= (led_wt <<

begin

if(time_flag==0)

if((led_sec0==8'b1001_1001)||(led_sec0==8'b1001_0000))

3'b011:

3'b100:

end

begin

if(time_flag==0)

begin

end

else

led_wt <= ~led_wt;

led_wt <= 15'h7fff ;

default: led_wt <= 15'b0;

endcase

3'b101:

default:

endcase

endmodule

module control (key_1,mode,cp_1,cp_50,wsh_sty[2:0] ,mode_change,led_min0,led_min1 ,led_sec0,

led_sec1,min_all1,min_all2,led_wt);

input [2:0]mode;

input cp_1,cp_50,key_1;

output [2:0] wsh_sty;

output mode_change;

output [7:0] led_min0,led_min1,led_sec0, led_sec1,min_all1,min_all2;

13

output[14:0] led_wt;

//wire [2:0]mode;

reg[2:0] wsh_sty;

reg[1:0]

reg

initial

led_show led_1(key_1,time_flag , mode, wsh_sty,cp_50,cp_1,led_min0,led_min1,led_sec0,

led_sec1,min_all1,min_all2,seccp);

water_station(key_1,led_sec0,cp_1,wsh_sty,mode,time_flag,led_wt);

always @ ( posedge seccp)

begin

if((~(key_1==0))&&(mode!=3'b000))

else

case(mode)

3'b000:

begin

wsh_sty<=3'b000;

wsh_flag<=1'b0;

dry_flag<=2'b00;

time_flag=0;

begin

end

wsh_sty <= wsh_sty;

wsh_flag <= wsh_flag;

dry_flag <= dry_flag;

time_flag <= time_flag;

mode_change <= mode_change;

begin

end

wsh_sty<=3'b000;

wsh_flag<=1'b0;

dry_flag<=2'b00;

dry_flag;

mode_change,wsh_flag;

reg[10:0] time_flag;

wire seccp;

end //断电状态将洗衣方式清零

3'b001,

3'b010,

3'b011:

begin

case(wsh_sty)

3'b000:

14

//注水

begin

if((time_flag>=11'd60)&&(wsh_flag==0))

if((time_flag>=11'd60)&&(wsh_flag==1))

if((time_flag>=11'd1800)&&(mode==3'b001))

if((time_flag>=11'd1200)&&(mode==3'b010))

if((time_flag>=11'd600)&&(mode==3'b011))

begin

time_flag=0;

wsh_sty<=3'b001; //转到洗衣模 end

else

begin

time_flag=0;

wsh_sty<=3'b100; //转到漂洗模 end

else

time_flag <= time_flag + 1'b1 ;

end

3'b001: //洗衣

begin

wsh_flag <= 1;

begin

time_flag=0;

wsh_sty<=3'b010; //转到排水模 end

else

begin

time_flag=0;

wsh_sty<=3'b010; //转到排水模 end

else

begin

time_flag=0;

wsh_sty<=3'b010; //转到排水模 end

else

time_flag <= time_flag +1'b1 ;

end

3'b010: //排水

15

时向外部表示已经洗完,请求改变模式

if((time_flag>=11'd60)&&(dry_flag<2'b10))

begin

if(time_flag>=11'd60)

begin

time_flag=0;

wsh_sty<=3'b011; //转到甩干模 end

else

time_flag <= time_flag + 1'b1 ;

end

3'b011: //甩干

begin

if((time_flag>=11'd60)&&(dry_flag>=2'b10))

begin

time_flag =0;

dry_flag <= 0;

wsh_sty <= 3'b000;

wsh_flag<=1'b0;

mode_change<=1; //高电平 end

else

begin

time_flag = 0;

wsh_sty <= 3'b000; //转到注水模 dry_flag <= dry_flag + 1'b1;

end

else

time_flag <= time_flag + 1'b1 ;

end

3'b100: //漂洗

begin

if(time_flag>=11'd300)

begin

time_flag=0;

wsh_sty<=3'b010; //转到甩干模 end

else

time_flag <= time_flag +1'b1 ;

16

end

end

wsh_sty <=3'b000; default:

endcase

3'b100: begin

case(wsh_sty)

时向外部表示已经洗完,请求改变模式

if((time_flag>=11'd60)&&(dry_flag<2'b01))

3'b000: //注水

begin

if(time_flag>=11'd60)

begin

time_flag=0;

wsh_sty<=3'b100; //转到漂洗模 end

else

time_flag <= time_flag + 1'b1;

end

3'b010: //排水

begin

if(time_flag>=11'd60)

begin

time_flag=0;

wsh_sty<=3'b011; //转到甩干模 end

else

time_flag <= time_flag + 1'b1 ;

end

3'b011: //甩干

begin

if((time_flag>=11'd60)&&(dry_flag>=2'b01))

begin

time_flag =0;

dry_flag <= 0;

wsh_sty <= 3'b000;

wsh_flag<=1'b0;

mode_change<=1; //高电平 end

else

17

求改变模式

begin

time_flag = 0;

wsh_sty <= 3'b000; //转到注水模 dry_flag <= dry_flag + 1'b1;

end

else

time_flag <= time_flag + 1'b1 ;

end

3'b100: //漂洗

begin

if(time_flag>=11'd300)

begin

time_flag=0;

wsh_sty<=3'b010; //转到排水模 end

else

time_flag <= time_flag + 1'b1 ;

end

default: wsh_sty <=3'b000;

endcase

end

3'b101: begin

wsh_sty <= 3'b011;//甩干

if(time_flag>=7'd60)

begin

time_flag=0;

wsh_sty <= 3'b000;

wsh_flag<=1'b0;

mode_change<=1;//高电平时向外部表示已经洗完,请 end

else

time_flag <= time_flag + 1'b1;

end

3'b110: begin

wsh_sty<=3'b000;

time_flag=0;

wsh_flag<=1'b0;

dry_flag<=2'b00;

end

3'b111: begin

18

end

end

wsh_sty<=3'b000;

time_flag=0;

wsh_flag<=1'b0;

dry_flag<=2'b00;

mode_change<=0;

endcase

endmodule

module counter_6(ncr, en,cp,q);

module counter_10 (nclr,clk,Q,out_0);

input clk, nclr;

output

output

[3:0]Q;

out_0;

input cp, ncr,en;

output

reg

[3:0] q;

[3:0] q;

always @ (posedge cp or negedge ncr)

begin

end

if(!ncr)

q <= 4'b0000;

else if(~en)

else

q <= q;

q <= q + 1'b1;

else if(q == 4'b0101) q <= 4'b0000;

endmodule

reg [3:0]Q;

reg out_0;

(!nclr) begin

begin

begin

Q <= 4'b000; out_0=0 ; end

Q <= 4'b000; out_0=1 ; end

Q <= Q+1'b1; out_0=0 ; end

always @(posedge clk or negedge nclr)

begin

if

else if (Q==9)

else

end

endmodule

module led_show ( key_1,time_flag , mode, wsh_sty,cp_50,cp_1,led_min0,led_min1,led_sec0,

led_sec1,min_all1,min_all2,seccp);

input [10:0]time_flag;

input [2:0]mode;

19

input [2:0]wsh_sty;

input cp_50,cp_1,key_1;

output [7:0] led_min0,led_min1,led_sec0, led_sec1,min_all1,min_all2;

output seccp;

wire [7:0] led_min0,led_min1,led_sec0, led_sec1,min_all1,min_all2,min_use,sec_use,min_all;

wire mincp,seccp ;

wire [10:0]time_flag;

wire [2:0]mode;

wire [2:0]wsh_sty;

reg [7:0] min_now,sec_now,sec_now_old,min_now_old,min_sy,min_sy_old;

reg en_time,en_time_all;

//initial mincp<=1;

counter_60 u1(en_time, seccp,sec_use);

counter_60 u2(en_time, mincp,min_use);

counter_60 u3(en_time_all,mincp,min_all);

assign

assign

always

@

if(time_flag[10:0]==11'b0) en_time<=0;

else

case(mode)

3'b000,

3'b110,

3'b111:

default:

en_time_all <= 0;

en_time_all <= 1;

en_time<=1;

mincp = key_1 ? (mincp) :(sec_use == 8'b00000000);

seccp = key_1 ? (seccp):(cp_1);

(posedge cp_50)

begin

endcase

sec_now_old <= 8'b01011010- sec_use;

if(sec_now_old[3:0]==4'b1010)

case(wsh_sty)

3'b001:

begin

case(mode)

3'b001:

3'b010:

min_now_old <= 8'b00101001 - min_use;

min_now_old <= 8'b00011001 - min_use;

20

begin

end

sec_now[3:0] <= 0;

sec_now[7:4] <= sec_now_old[7:4]+4'b0001;

else sec_now <= sec_now_old;

end

3'b011:

endcase

min_now_old <= 8'b00001001 - min_use;

default:min_now_old <=0;

3'b100:

default:

min_now_old <= 8'b00000100 - min_use;

min_now_old <= 0;

endcase

if(min_now_old[3:0]==4'b1010)

case(mode)

3'b001:

begin

end

begin

end

begin

end

begin

end

min_sy <= 0;

min_sy_old <= 8'b00011001 - min_all;

if(min_sy_old[3:0]<4'b0100) min_sy <= min_sy_old - 8'd10;

else min_sy <= min_sy_old - 8'b00000100;

min_sy_old <= 8'b00101001 - min_all ;

if(min_sy_old[3:0]==4'b0000) min_sy <=min_sy_old - 8'd7;

else min_sy <= min_sy_old - 8'b00000001;

min_sy_old <= 8'b00111001 - min_all ;

if(min_sy_old[3:0]==4'b0000) min_sy <=min_sy_old - 8'd7;

else min_sy <= min_sy_old - 8'b00000001;

min_sy_old <= 8'b01001001 - min_all ;

if(min_sy_old[3:0]==4'b0000) min_sy <=min_sy_old - 8'd7;

else min_sy <= min_sy_old - 8'b00000001;

begin

end

min_now[3:0] <= 0;

min_now[7:4] <= min_now_old[7:4]+4'b0001;

else min_now <= min_now_old ;

3'b010:

3'b011:

3'b100:

default:

endcase

21

end

led led_1(cp_50,sec_now, led_sec0, led_sec1);

led led_2(cp_50,min_now, led_min0, led_min1);

led led_3(cp_50,min_sy, min_all1, min_all2);

endmodule

module led(cp_50,BCD,led0, led1);

input [7:0] BCD;

input cp_50;

output [7:0] led0, led1;

reg [7:0] led0, led1;

always @( posedge cp_50)

begin

casez (BCD[3:0])

casez (BCD[7:4])

4'd0 : led1 = 8'b1100_0000;

4'd1 : led1 = 8'b1111_1001;

4'd2 : led1 = 8'b1010_0100;

4'd3 : led1 = 8'b1011_0000;

4'd4 : led1 = 8'b1001_1001;

4'd5 : led1 = 8'b1001_0010;

4'd6 : led1 = 8'b1000_0010;

4'd7 : led1 = 8'b1111_1000;

4'd8 : led1 = 8'b1000_0000;

4'd9 : led1 = 8'b1001_0000;

default: led0 = 8'b1111_1111;

22

4'd0 : led0 = 8'b1100_0000;

4'd1 : led0 = 8'b1111_1001;

4'd2 : led0 = 8'b1010_0100;

4'd3 : led0 = 8'b1011_0000;

4'd4 : led0 = 8'b1001_1001;

4'd5 : led0 = 8'b1001_0010;

4'd6 : led0 = 8'b1000_0010;

4'd7 : led0 = 8'b1111_1000;

4'd8 : led0 = 8'b1000_0000;

4'd9 : led0 = 8'b1001_0000;

default: led0 = 8'b1111_1111;

endcase

end

endcase

endmodule

/*******************************************************************************************************

***********************************lcd显示部分**********************************************************

***********************************用lcd显示当前的mode

*************************************************

********************************************************************************************************

*/

module lcd_show(

);

wire[7:0] LCD_D_1;

wire LCD_RS_1;

wire LCD_RW_1;

wire LCD_EN_1;

wire DLY_RST;

assign LCD_DATA=LCD_D_1;

assign LCD_RS=LCD_RS_1;

assign LCD_RW=LCD_RW_1;

assign LCD_EN=LCD_EN_1;

assign LCD_ON=1'b1;

assign LCD_BLON=1'b1;

Reset_Delay r0(.iCLK(CLOCK_50), .oRESET(DLY_RST),.RST_N(RST_N));

LCD1602_TEST u1(

.iCLK(CLOCK_50),

.iRST_N(DLY_RST),

.mode(mode),

23

input CLOCK_50,

input RST_N,

input [2:0]mode,// new

output[7:0] LCD_DATA,

input[2:0] wsh_sty,

input [2:0]mode_slt,

output LCD_EN,

output LCD_RS,

output LCD_RW,

output LCD_ON,

output LCD_BLON

.mode_slt(mode_slt),

.wsh_sty(wsh_sty),

.LCD_DATA(LCD_D_1),

.LCD_RW(LCD_RW_1),

.LCD_EN(LCD_EN_1),

.LCD_RS(LCD_RS_1)

);

endmodule

//RST_N初始延迟代码:

module Reset_Delay(iCLK,oRESET,RST_N);

input iCLK,RST_N;

output reg oRESET;

reg[19:0] Cont;

always@(posedge iCLK)

begin

if(~RST_N)

begin

Cont<=0;

oRESET<=1'b0;

end

if((Cont!=20'hfffff)&&(RST_N))

begin

Cont<=Cont+1'b1;

oRESET<=1'b0;

end

else

oRESET<=1'b1;

end

endmodule

//底层代码LCD1602_TEST:

module LCD1602_TEST(

input iCLK,iRST_N,

input [2:0]mode ,

24

//初始化的延时部分

input [2:0]mode_slt ,

input [2:0]wsh_sty,

output[7:0] LCD_DATA,

output LCD_RS,LCD_RW,LCD_EN

);

reg[5:0] LUT_INDEX;

reg[8:0] LUT_DATA;

reg[5:0] mLCD_ST;

reg[17:0] mDLY;

reg[7:0] mLCD_DATA;

reg mLCD_Start;

reg mLCD_RS;

reg [2:0]mode_flag,mode_slt_flag;

reg [3:0]wsh_sty_flag;

wire mLCD_Done;

parameter LCD_INITIAL = 0;

parameter LCD_LINE1 = 5; //初始化命令有5个parameter LCD_CH_LINE = LCD_LINE1+16; //换行parameter LCD_LINE2 = LCD_LINE1+16+1;

parameter LUT_SIZE = LCD_LINE1+32+1;

initial

begin

mode_flag<=3'b000;

end

always@(posedge iCLK or negedge iRST_N)

begin

if(!iRST_N)

部清零

begin

LUT_INDEX <= 0;

mLCD_ST <= 0;

mDLY <= 0;

mLCD_Start <= 0;

mLCD_DATA <= 0;

mLCD_RS <= 0;

end

else

begin

if(mode_flag !=mode)

begin

mode_flag<=mode;

LUT_INDEX <= 0;

end

if(mode_slt_flag !=mode_slt)

25

//程序的初始化,全

begin

end

if(wsh_sty_flag != wsh_sty)

begin

wsh_sty_flag<=wsh_sty;

mode_slt_flag<=mode_slt;

LUT_INDEX <= 0;

LUT_INDEX <= 0;

end

if(LUT_INDEX

begin

序需要的时延

case(mLCD_ST)

0: begin

mLCD_DATA <= LUT_DATA[7:0];

是显示位

mLCD_RS <= LUT_DATA[8];

是控制位

mLCD_Start <= 1;

mLCD_ST <= 1;

end

1: begin

if(mLCD_Done)

否已经显示

begin

mLCD_Start <= 0;

经显示重新归零,否则保持原来的1

mLCD_ST <= 2;

转到下一步

end

end

2: begin

if(mDLY<16'hffff)

mDLY <= mDLY+17'b1;

else

begin

mDLY <= 0;

mLCD_ST <= 3;

转到下一步

end

end

3: begin

26

//提供程//低八位//第九位//检查是//如果已 //跳//延时

//归 //跳

转到初始状态

示光标

针清零

址指针加一

(power off)

end

end

end

LUT_INDEX <= LUT_INDEX+6'b1;

mLCD_ST <= 0;

//自加

//跳endcase

begin

case(mode)

3'b000:

begin

end

case(LUT_INDEX)

LCD_INITIAL+0: LUT_DATA <= 9'h038; //设置16x2显示,LCD_INITIAL+1: LUT_DATA <= 9'h00C; //设置开显示,不显LCD_INITIAL+2: LUT_DATA <= 9'h001; //显示清零,数据指LCD_INITIAL+3: LUT_DATA <= 9'h006; //写一个字符后地LCD_INITIAL+4: LUT_DATA <= 9'h080; //第一行首地址

LCD_LINE1+0: LUT_DATA <= 9'h120; // 未开电源LCD_LINE1+3: LUT_DATA <= 9'h170; //p

LCD_LINE1+4: LUT_DATA <= 9'h16f; //o

LCD_LINE1+5: LUT_DATA <= 9'h177; //w

LCD_LINE1+6: LUT_DATA <= 9'h165; //e

LCD_LINE1+7: LUT_DATA <= 9'h172; //r

LCD_LINE1+10: LUT_DATA <= 9'h16f; //o

LCD_LINE1+11: LUT_DATA <= 9'h166; //f

LCD_LINE1+12: LUT_DATA <= 9'h166; //f

LCD_CH_LINE: LUT_DATA <= 9'h0C0;

default: LUT_DATA <= 9'h120;

5x7点阵,8位数据接口

endcase

3'b001,

3'b010,

3'b011,

3'b100,

3'b101:

begin

case(LUT_INDEX)

LCD_INITIAL+0: LUT_DATA <= 9'h038; //设置16x2显示,5x7点阵,8位数据接口

27

数据指针清零

LCD_INITIAL+1: LUT_DATA <= 9'h00C; //设置开显LCD_INITIAL+2: LUT_DATA <= 9'h001; //显示清零,LCD_INITIAL+3: LUT_DATA <= 9'h006; //写一个字符LCD_INITIAL+4: LUT_DATA <= 9'h080; //第一行首地LCD_LINE1+6: LUT_DATA <= 9'h16d; //m

示,不显示光标

后地址指针加一

<= 9'h131;

<= 9'h132;

<= 9'h133;

<= 9'h134;

<= 9'h135;

LUT_DATA <= 9'h120;

<= 9'h169;//i

<= 9'h120;//120

<= 9'h120;//120

<= 9'h120;//120

<= 9'h120;//120

LUT_DATA <= 9'h120;

LCD_LINE1+7:

LCD_LINE1+8:

LCD_LINE1+9:

LCD_LINE1+11:

LCD_CH_LINE:

LCD_LINE2+5:

28

LUT_DATA <= 9'h16f; //o

LUT_DATA <= 9'h164; //d

LUT_DATA <= 9'h165; //e

begin

case(mode)

3'b001: LUT_DATA

3'b010: LUT_DATA

3'b011: LUT_DATA

3'b100: LUT_DATA

3'b101: LUT_DATA

default:

endcase

end

LUT_DATA <= 9'h0C0;

begin

case(wsh_sty)

3'b000: LUT_DATA

3'b001: LUT_DATA

3'b010: LUT_DATA

3'b011: LUT_DATA

3'b100: LUT_DATA

default:

endcase

end

LCD_LINE2+6: begin

<= 9'h16e;//n

<= 9'h177;//w

<= 9'h164;//d

<= 9'h120;//120

<= 9'h170;//p

LUT_DATA <= 9'h120;

<= 9'h16a;//j

<= 9'h161;//a

<= 9'h172;//r

<= 9'h164;//d

<= 9'h16f;//o

LUT_DATA <= 9'h120;

<= 9'h165;//e

<= 9'h173;//s

<= 9'h161;//a

<= 9'h172;//r

LCD_LINE2+7:

LCD_LINE2+8:

29

case(wsh_sty)

3'b000:

3'b001:

3'b010:

3'b011:

3'b100:

default:

endcase

end

begin

case(wsh_sty)

3'b000:

3'b001:

3'b010:

3'b011:

3'b100:

default:

endcase

end

begin

case(wsh_sty)

3'b000:

3'b001:

3'b010:

3'b011:

3'b100:

LUT_DATA

LUT_DATA

LUT_DATA

LUT_DATA

LUT_DATA

LUT_DATA

LUT_DATA

LUT_DATA

LUT_DATA

LUT_DATA

LUT_DATA

LUT_DATA

LUT_DATA

LUT_DATA

LUT_DATA

<= 9'h174;//t

end

default:

LUT_DATA <= 9'h120;

endcase

LCD_LINE2+9: begin

<= 9'h163;//c

<= 9'h168;//h

<= 9'h169;//i

<= 9'h179;//y

<= 9'h163;//c

LUT_DATA <= 9'h120;

<= 9'h174;//t

<= 9'h120;//120

<= 9'h16e;//n

<= 9'h120;//120

<= 9'h168;//h

LUT_DATA <= 9'h120;

end

3'b110:

begin

case(wsh_sty)

3'b000:

3'b001:

3'b010:

3'b011:

3'b100:

default:

endcase

end

LCD_LINE2+10: begin

case(wsh_sty)

3'b000:

3'b001:

3'b010:

3'b011:

3'b100:

default:

endcase

end

default: LUT_DATA <= 9'h120;

endcase

case(LUT_INDEX)

30

LUT_DATA

LUT_DATA

LUT_DATA

LUT_DATA

LUT_DATA

LUT_DATA

LUT_DATA

LUT_DATA

LUT_DATA

LUT_DATA

示光标

针清零

址指针加一

end

LCD_INITIAL+0: LUT_DATA <= 9'h038; //设置16x2显示,LCD_INITIAL+1: LUT_DATA <= 9'h00C; //设置开显示,不显LCD_INITIAL+2: LUT_DATA <= 9'h001; //显示清零,数据指LCD_INITIAL+3: LUT_DATA <= 9'h006; //写一个字符后地LCD_INITIAL+4: LUT_DATA <= 9'h080; //第一行首地址

LCD_LINE1+1: LUT_DATA <= 9'h170; //p

LCD_LINE1+2: LUT_DATA <= 9'h16c; //l

LCD_LINE1+3: LUT_DATA <= 9'h165; //e

LCD_LINE1+4: LUT_DATA <= 9'h161; //a

LCD_LINE1+5: LUT_DATA <= 9'h173; //s

LCD_LINE1+6: LUT_DATA <= 9'h165; //e

LCD_LINE1+9: LUT_DATA <= 9'h173; //s

LCD_LINE1+10: LUT_DATA <= 9'h165; //e

LCD_LINE1+11: LUT_DATA <= 9'h16c; //l

LCD_LINE1+12: LUT_DATA <= 9'h165; //e

LCD_LINE1+13: LUT_DATA <= 9'h163; //c

LCD_LINE1+14: LUT_DATA <= 9'h174; //t

LCD_CH_LINE: LUT_DATA <= 9'h0C0;

LCD_LINE2+5: LUT_DATA <= 9'h16D; //m

LCD_LINE2+6: LUT_DATA <= 9'h16F; //o

LCD_LINE2+7: LUT_DATA <= 9'h164; //d

LCD_LINE2+8: LUT_DATA <= 9'h165; //e

LCD_LINE2+10:begin

if(mode_slt==3'b001)

else

end

LUT_DATA <= 9'h13F;

LUT_DATA <= 9'h131;

LUT_DATA <= 9'h132;

LUT_DATA <= 9'h133;

LUT_DATA <= 9'h134;

LUT_DATA <= 9'h135;

else if(mode_slt==3'b010)

else if(mode_slt==3'b011)

else if(mode_slt==3'b100)

else if(mode_slt==3'b101)

5x7点阵,8位数据接口

LCD_LINE2+12: LUT_DATA <= 9'h13f;

default: LUT_DATA <= 9'h120;

endcase

31

示光标

3'b111:

begin

case(LUT_INDEX)

LCD_INITIAL+0: LUT_DATA <= 9'h038; //设置16x2显示,LCD_INITIAL+1: LUT_DATA <= 9'h00C; //设置开显示,不显LCD_INITIAL+2: LUT_DATA <= 9'h001; //显示清零,数据指5x7点阵,8位数据接口

针清零

LCD_INITIAL+3: LUT_DATA

址指针加一

LCD_INITIAL+4: LUT_DATA

LCD_LINE1+5: LUT_DATA

LCD_LINE1+6: LUT_DATA

LCD_LINE1+7: LUT_DATA

LCD_LINE1+8: LUT_DATA

LCD_LINE1+9: LUT_DATA

LCD_LINE1+10: LUT_DATA

LCD_CH_LINE: LUT_DATA

LCD_LINE2+6: LUT_DATA

LCD_LINE2+7: LUT_DATA

LCD_LINE2+8: LUT_DATA

LCD_LINE2+9: LUT_DATA

default: LUT_DATA

endcase

end

endcase

end

end

LCD1602_Controller u0 (

.iDATA(mLCD_DATA),

.iRS(mLCD_RS),

.iStart(mLCD_Start),

.oDone(mLCD_Done),

.iCLK(iCLK),

.iRST_N(iRST_N),

.LCD_DATA(LCD_DATA),

.LCD_RW(LCD_RW),

.LCD_EN(LCD_EN),

.LCD_RS(LCD_RS)

);

endmodule

32

<= 9'h006; //写一个字符后地<= 9'h080; //第一行首地址

<= 9'h177; //w

<= 9'h161; //a

<= 9'h173; //s

<= 9'h168; //h

<= 9'h165; //e

<= 9'h172; //r

<= 9'h0C0;

<= 9'h16F; //o

<= 9'h176; //v

<= 9'h165; //e

<= 9'h172; //r

<= 9'h120;

//底层代码LCD1602_Controller:

module LCD1602_Controller(

input iCLK,iRST_N,

input iRS,iStart,

input[7:0] iDATA,

output reg oDone,

output[7:0] LCD_DATA,

output LCD_RS,

output LCD_RW,

output reg LCD_EN

);

reg[4:0] Cont;

reg[1:0] ST;

reg preStart,mStart;

assign LCD_DATA = iDATA;

assign LCD_RS = iRS;

assign LCD_RW = 1'b0;

parameter CLK_Divide = 16;

always@(posedge iCLK or negedge iRST_N)

begin

if(!iRST_N)

begin

oDone <= 1'b0;

LCD_EN <= 1'b0;

preStart<= 1'b0;

mStart <= 1'b0;

Cont <= 0;

ST <= 0;

end

else

begin

preStart <= iStart;

if({preStart,iStart}==2'b01)

begin

mStart <= 1'b1;

oDone <= 1'b0;

end

if(mStart)

begin

33

//提

供程序需要的脉冲

end

endmodule

module HZ_1 (input_0,nclr,output_fin);

input input_0,nclr;

output output_fin;

wire [3:0]q_0,q_1,q_2,q_3,q_4,q_5,q_6,q_7;

wire Q_0,Q_1,Q_2,Q_3,Q_4,Q_5,Q_6;

counter_10 u1 (nclr,input_0,q_0[3:0],Q_0);

counter_10 u2 (nclr,Q_0,q_1[3:0],Q_1);

counter_10 u3 (nclr,Q_1,q_2[3:0],Q_2);

counter_10 u4 (nclr,Q_2,q_3[3:0],Q_3);

counter_10 u5 (nclr,Q_3,q_4[3:0],Q_4);

counter_10 u6 (nclr,Q_4,q_5[3:0],Q_5);

counter_10 u7 (nclr,Q_5,q_6[3:0],Q_6);

counter_5 u8 (nclr,Q_6,q_7[3:0],output_fin);

endmodule

module counter_60(nclr, cp,ct);

input cp, nclr;

output [7:0] ct; // 模六十计数器输出信号

34

end

case(ST)

end

0: ST <= 1;

1: begin

end

end

end

LCD_EN <= 1'b0;

mStart <= 1'b0;

oDone <= 1'b1;

Cont <= 0;

ST <= 0;

if(Cont

else

ST <= 3;

Cont <= Cont+5'b1;

LCD_EN <= 1'b1;

ST <= 2;

2: begin

3: begin

endcase

wire [7:0] ct;

wire cp_6,en;

counter_10

counter_6

assign

// 输出 8421 BCD 码

uc0 (nclr,cp,ct[3:0],cp_6);

uc1 (nclr,en,cp,ct[7:4]);

en = (ct[3:0] == 4'h9); // 产生计数器十位使能信号

endmodule

module counter_5 (nclr,clk,Q,out_0);

input clk, nclr;

output [3:0]Q;

output out_0;

reg [3:0]Q;

reg out_0;

always @(posedge clk or negedge nclr)

begin

if (!nclr) begin

else if (Q==3) begin

else if (Q==4) begin

else begin

end

endmodule

Q <= 4'b000; out_0=0 ;

Q <= Q+1'b1; out_0=1

Q <= 4'b000; out_0=0 ;

Q <= Q+1'b1; out_0=0

35

end

; end

end

; end


本文发布于:2024-09-24 11:25:36,感谢您对本站的认可!

本文链接:https://www.17tex.com/fanyi/17730.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:模块   模式   显示   洗衣   表示   状态   程序
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2024 Comsenz Inc.Powered by © 易纺专利技术学习网 豫ICP备2022007602号 豫公网安备41160202000603 站长QQ:729038198 关于我们 投诉建议