当前位置:   article > 正文

FPGA自动洗衣机的设计与验证(Verilog编写)_fpga洗衣机设计

fpga洗衣机设计

目的及要求

        1.洗衣机的工作步骤为洗衣、漂洗和脱水三个过程,工作时间分别为:洗 衣45秒,漂洗30 秒,脱水15 秒;

        2.用一个按键实现洗衣程序的手动选择:A、单洗涤;B、单漂洗;C、单脱水;D、漂洗和脱水;E、洗涤、漂洗和脱水全过程;

        3. 用3个LED灯分别表示当前工作状态,并且以1HZ频率闪烁(洗衣、漂洗和脱水),数码管倒计时显示每个步骤剩余的工作时间,这里采用数码管动态显示。全部过程结束后,应提示使用者;

        4. 用一个按键实现暂停洗衣和继续洗衣的控制,暂停后继续洗衣应回到暂停之前保留的状态;

        5.洗涤和漂洗过程中电机正运转方式为:正转5s ->暂停2s ->反转5s,若洗涤时间没到则重复以上过程,脱水则一直正转。

设计规范:功能、性能要求、端口信号说明;

类型

名称

位宽

描述

input

Clk

1

时钟信号125MHZ

input

Rst

1

复位

input

Mode

1

模式选择

input

Sta_Pause

1

启动/暂停

output

Beep

1

洗衣完成

output

Led_wash

1

洗涤状态灯

output

Led_rinse

1

漂洗状态灯

output

Led_dry

1

脱水状态灯

output

Seg_sel

4

位选信号

output

Seg_led

7

七段管段选信号

output

Roll_pos

1

电机正转

output

Roll_neg

1

电机反转

设计程序代码(125M是真实上板的频率,这里为了提高速度,进行仿真时,需要把第一行的125000000改成50000)

  1. `define CLK_NUM 125_000_000 //输入的时钟频率
  2. //
  3. // Company:
  4. // Engineer:
  5. //
  6. // Create Date: 2023/11/24 09:50:24
  7. // Design Name:
  8. // Module Name: washing_machine
  9. // Project Name:
  10. // Target Devices:
  11. // Tool Versions:
  12. // Description:
  13. //
  14. // Dependencies:
  15. //
  16. // Revision:
  17. // Revision 0.01 - File Created
  18. // Additional Comments:
  19. //
  20. //
  21. module washing_machine(
  22. input Clk,
  23. input Rst,Mode,Sta_Pause,
  24. output wire Led_wash,
  25. output wire Led_rinse,
  26. output wire Led_dry,
  27. output reg Beep,
  28. output wire Roll_neg,
  29. output wire Roll_pos,
  30. output [3:0] seg_sel,
  31. output [6:0] seg_led
  32. );
  33. parameter Mode0=5'b00000,ModeA=5'b00001,ModeB=5'b00010,ModeC=5'b00100,ModeD=5'b01000,ModeE=5'b10000;
  34. parameter forward=2'b01,stop=2'b00,backward=2'b10;
  35. parameter wash=3'b001,rinse=3'b010,dry=3'b100;
  36. reg [4:0] next_state,present_state;
  37. reg [2:0] work_state;
  38. reg [1:0] motor_state,motor_prestate;
  39. reg [26:0] hz_cnt;
  40. reg [2:0] cnt_motor;
  41. reg Clk_hz;
  42. reg Mode_last;
  43. reg do_not;
  44. reg [5:0] minute;
  45. reg [5:0] sec;
  46. reg [3:0] status;//模式显示
  47. reg [2:0] cnt_beep;
  48. wire time_flag;
  49. wire Mode_d; //_d为去抖
  50. wire Sta_Pause_d;
  51. wire [3:0] minute_ge;
  52. wire [3:0] minute_shi;
  53. wire [3:0] sec_ge;
  54. wire [3:0] sec_shi;
  55. wire [15:0] data;
  56. //状态转移逻辑,1/选择工作模式
  57. always @(posedge Clk or negedge Rst) begin
  58. if(!Rst)
  59. next_state<=ModeA;
  60. else if(time_flag)
  61. next_state<=ModeA;
  62. else begin
  63. Mode_last <= Mode_d;
  64. case(next_state)
  65. ModeA: begin
  66. if(Mode_last==0 && Mode_d==1) begin
  67. next_state<=ModeB;
  68. end
  69. else next_state<=ModeA;
  70. end
  71. ModeB: begin
  72. if(Mode_last==0 && Mode_d==1) begin
  73. next_state<=ModeC;
  74. end
  75. else next_state<=ModeB;
  76. end
  77. ModeC: begin
  78. if(Mode_last==0 && Mode_d==1) begin
  79. next_state<=ModeD;
  80. end
  81. else next_state<=ModeC;
  82. end
  83. ModeD: begin
  84. if(Mode_last==0 && Mode_d==1) begin
  85. next_state<=ModeE;
  86. end
  87. else next_state<=ModeD;
  88. end
  89. ModeE: begin
  90. if(Mode_last==0 && Mode_d==1) begin
  91. next_state<=ModeA;
  92. end
  93. else next_state<=ModeE;
  94. end
  95. endcase
  96. end
  97. end
  98. //状态跳转,Mode0用于表示实际工作状态为空闲,2/按下开始
  99. always@(posedge Clk or negedge Rst) begin
  100. if(!Rst)
  101. begin
  102. present_state<=Mode0;
  103. end
  104. else if(present_state==Mode0 && Sta_Pause_d==1) begin
  105. present_state<= next_state;
  106. end
  107. else if(minute==6'd0 && sec==6'd0)
  108. begin
  109. present_state <= Mode0;
  110. end
  111. end
  112. //分、秒控制模块
  113. always@(posedge Clk_hz or negedge Rst) begin
  114. if(!Rst)
  115. begin
  116. sec<=6'd0;
  117. minute<=6'd0;
  118. end
  119. else if(present_state==Mode0) begin
  120. case(next_state)
  121. ModeA: begin minute <= 6'd0; sec <= 6'd45; status <= 4'hA; end
  122. ModeB: begin minute <= 6'd0; sec <= 6'd30; status <= 4'hB; end
  123. ModeC: begin minute <= 6'd0; sec <= 6'd15; status <= 4'hC; end
  124. ModeD: begin minute <= 6'd0; sec <= 6'd45; status <= 4'hD; end
  125. ModeE: begin minute <= 6'd1; sec <= 6'd30; status <= 4'hE; end
  126. endcase
  127. end
  128. else if(!do_not) begin //暂停工作
  129. sec<=sec;
  130. minute<=minute;
  131. status <= status;
  132. end
  133. else if(minute>=6'd1 && sec==6'd0) begin
  134. sec<=6'd59;
  135. minute<=minute-1;
  136. status <= status;
  137. end
  138. else if(minute==6'd0 && sec==6'd0) //工作结束
  139. begin
  140. sec<=6'd0;
  141. minute<=6'd0;
  142. status <= 4'h0;
  143. end
  144. else begin
  145. sec<=sec-1;
  146. minute<=minute;
  147. status <= status;
  148. end
  149. end
  150. assign time_flag = (minute==6'd0 && sec==6'd1) ? 1'b1:1'b0;//最后一秒准备报警
  151. //3/选择工作状态
  152. always @(posedge Clk or negedge Rst) begin
  153. if(!Rst || present_state==Mode0)
  154. work_state<=3'b000;
  155. else if(present_state==ModeA) begin
  156. work_state <= wash;
  157. end
  158. else if(present_state==ModeB) begin
  159. work_state <= rinse;
  160. end
  161. else if(present_state==ModeC) begin
  162. work_state <= dry;
  163. end
  164. else if(present_state==ModeD) begin
  165. if(sec<=30) work_state <= dry;
  166. else work_state <= rinse;
  167. end
  168. else if(present_state==ModeE) begin
  169. if(minute==0 && sec<=15) work_state <= dry;
  170. else if(minute==0 && sec<=45) work_state <= rinse;
  171. else work_state <= wash;
  172. end
  173. end
  174. //电机状态,4/具体到电机转动方向
  175. always @(posedge Clk_hz or negedge Rst) begin
  176. if(!Rst || present_state==Mode0) begin
  177. motor_state<=stop;
  178. motor_prestate <= backward;
  179. cnt_motor <= 0;
  180. end
  181. else if(!do_not) begin //暂停键按下
  182. motor_state <= stop;
  183. motor_prestate <= forward;
  184. cnt_motor <= 0;
  185. end
  186. else if(work_state==dry) begin
  187. motor_state <= forward;
  188. end
  189. else if((sec>45 && sec<=47)||(minute==1 && sec>15 && sec<=17)) begin //状态转换前电机停止
  190. motor_state<=stop;
  191. motor_prestate <= backward;
  192. cnt_motor <= 0;
  193. end
  194. else begin
  195. case(motor_state)
  196. forward: begin //正转5s停
  197. if(cnt_motor==3'd4) begin
  198. motor_state <= stop;
  199. motor_prestate <= forward; //标记停前转动方向
  200. cnt_motor <= 0;
  201. end
  202. else cnt_motor <= cnt_motor+1'd1;
  203. end
  204. stop: begin
  205. if(cnt_motor==3'd1 && motor_prestate == forward) begin
  206. motor_state <= backward;
  207. cnt_motor <= 0;
  208. end
  209. else if(cnt_motor==3'd1 && motor_prestate == backward) begin
  210. motor_state <= forward;
  211. cnt_motor <= 0;
  212. end
  213. else cnt_motor <= cnt_motor+1'd1;
  214. end
  215. backward: begin
  216. if(cnt_motor==3'd4) begin
  217. motor_state <= stop;
  218. cnt_motor <= 0;
  219. motor_prestate <= backward;
  220. end
  221. else cnt_motor <= cnt_motor+1'd1;
  222. end
  223. endcase
  224. end
  225. end
  226. //暂停启动控制,6/暂停
  227. always @(posedge Sta_Pause_d or negedge Rst) begin
  228. if(!Rst)
  229. do_not<=1'b0;
  230. else
  231. do_not<= ~do_not;
  232. end
  233. //分频,得到1hz的时钟
  234. always @(posedge Clk or negedge Rst) begin
  235. if(!Rst) begin
  236. hz_cnt<=27'd0;
  237. Clk_hz<=1'd0;
  238. end
  239. else if(hz_cnt==`CLK_NUM/2-1)
  240. begin
  241. hz_cnt<=27'd0;
  242. Clk_hz<=~Clk_hz;
  243. end
  244. else
  245. hz_cnt<=hz_cnt+1;
  246. end
  247. //蜂鸣器模块 cnt_beep在计数1-6内响
  248. always @(posedge Clk_hz or negedge Rst) begin
  249. if(!Rst) begin
  250. Beep<=0;
  251. cnt_beep<=0;
  252. end
  253. else if(time_flag) cnt_beep <= cnt_beep+1;
  254. else if(cnt_beep >= 3'd1 && cnt_beep <= 3'd6) begin
  255. cnt_beep <= cnt_beep+1;
  256. Beep<=1;
  257. end
  258. else if(cnt_beep == 3'd7) begin
  259. cnt_beep <= 0;
  260. Beep<=0;
  261. end
  262. else
  263. Beep<=0;
  264. end
  265. //led指示模块
  266. assign Led_wash=(work_state==wash)? 1'b1 : 1'b0;
  267. assign Led_rinse=(work_state==rinse)? 1'b1 : 1'b0;
  268. assign Led_dry=(work_state==dry)? 1'b1 : 1'b0;
  269. //电机转动
  270. assign Roll_pos=(motor_state==forward)? 1'b1 : 1'b0;
  271. assign Roll_neg=(motor_state==backward)? 1'b1 : 1'b0;
  272. //数据输出
  273. assign minute_ge=minute%10;
  274. assign minute_shi=minute/10;
  275. assign sec_ge=sec%10;
  276. assign sec_shi=sec/10;
  277. assign data={status,minute_ge,sec_shi,sec_ge};
  278. //数码管的例化
  279. seg_led seg_led_inst(
  280. .Clk (Clk),
  281. .Rst (Rst),
  282. .data (data),
  283. .sel (seg_sel),
  284. .seg_led (seg_led)
  285. );
  286. //按键去抖例化
  287. debounce debounce_Sta(
  288. .Clk (Clk),
  289. .Rst (Rst),
  290. .btn (Sta_Pause),
  291. .btn_deb (Sta_Pause_d)
  292. );
  293. debounce debounce_Mode(
  294. .Clk (Clk),
  295. .Rst (Rst),
  296. .btn (Mode),
  297. .btn_deb (Mode_d)
  298. );
  299. endmodule
  300. //数码管显示模块
  301. module seg_led(
  302. input Clk,Rst,
  303. input [15:0] data,
  304. output reg [3:0] sel,
  305. output reg [6:0] seg_led
  306. );
  307. reg [15:0] ms_cnt;
  308. reg ms_clk;
  309. reg [3:0] num_display;
  310. reg [15:0] num;
  311. reg [1:0] sel_num; //选择哪一位数码管被点亮
  312. //4位数码管赋值
  313. always @(posedge Clk or negedge Rst) begin
  314. if(!Rst)
  315. num<=16'd0;
  316. else
  317. begin
  318. num[15:12] <= data[15:12];
  319. num[11:8] <= data[11:8];
  320. num[ 7:4] <= data[7:4];
  321. num[ 3:0] <= data[3:0];
  322. end
  323. end
  324. always @(posedge Clk or negedge Rst) begin //产生1ms脉冲
  325. if(!Rst)
  326. begin
  327. ms_cnt<=16'd0;
  328. ms_clk<=1'b0;
  329. end
  330. else if(ms_cnt==`CLK_NUM/2000-1)
  331. begin
  332. ms_cnt<=16'd0;
  333. ms_clk<=~ms_clk;
  334. end
  335. else
  336. ms_cnt<=ms_cnt+1;
  337. end
  338. //每毫秒选择管
  339. always @(posedge ms_clk or negedge Rst) begin
  340. if(!Rst)
  341. sel_num<=0;
  342. else
  343. sel_num<=sel_num+1;
  344. end
  345. //选择管译码
  346. always @(posedge Clk or negedge Rst) begin
  347. if(!Rst)
  348. sel<=4'b1111;
  349. else
  350. begin
  351. case(sel_num)
  352. 3'd0: begin
  353. sel<= 4'b1110; //显示数码管最低位
  354. num_display<=num[3:0];
  355. end
  356. 3'd1: begin
  357. sel<= 4'b1101; //显示数码管第1位
  358. num_display<=num[7:4];
  359. end
  360. 3'd2: begin
  361. sel<= 4'b1011; //显示数码管第2位
  362. num_display<=num[11:8];
  363. end
  364. 3'd3: begin
  365. sel<= 4'b0111; //显示数码管第3位
  366. num_display<=num[15:12];
  367. end
  368. default sel<= 4'b1111;
  369. endcase
  370. end
  371. end
  372. //数字译码
  373. always @(posedge Clk or negedge Rst) begin
  374. if(!Rst)
  375. seg_led<=7'b100_0000;
  376. else
  377. begin
  378. case(num_display)
  379. 4'h0 : seg_led <= 7'b100_0000;
  380. 4'h1 : seg_led <= 7'b111_1001;
  381. 4'h2 : seg_led <= 7'b010_0100;
  382. 4'h3 : seg_led <= 7'b011_0000;
  383. 4'h4 : seg_led <= 7'b001_1001;
  384. 4'h5 : seg_led <= 7'b001_0010;
  385. 4'h6 : seg_led <= 7'b000_0010;
  386. 4'h7 : seg_led <= 7'b111_1000;
  387. 4'h8 : seg_led <= 7'b000_0000;
  388. 4'h9 : seg_led <= 7'b001_0000;
  389. 4'hA: seg_led <= 7'b000_1000; //A
  390. 4'hB : seg_led <= 7'b000_0011;
  391. 4'hC : seg_led <= 7'b100_0110;
  392. 4'hD : seg_led <= 7'b010_0001;
  393. 4'hE : seg_led <= 7'b000_0110;
  394. 4'hF : seg_led <= 7'b000_1110;
  395. default : seg_led <= 7'b100_0000;
  396. endcase
  397. end
  398. end
  399. endmodule
  400. //按键去抖模块
  401. module debounce(input wire btn,Clk,Rst, //按键输入信号
  402. output reg btn_deb //去抖后的按键信号
  403. );
  404. parameter debounce_time = `CLK_NUM/500 ; //去抖时间
  405. reg [22:0] counter ; //计数器
  406. //状态机
  407. parameter STATE_IDLE = 2'b00;
  408. parameter STATE_PRE_DEBOUNCE = 2'b01;
  409. parameter STATE_DEBOUNCE = 2'b10;
  410. reg [1:0] state = STATE_IDLE;
  411. always @(posedge Clk or negedge Rst) begin
  412. if(!Rst) begin
  413. counter <=0;
  414. state <= STATE_IDLE;
  415. btn_deb <= 1'b0;
  416. end
  417. else begin
  418. case (state)
  419. STATE_IDLE: begin
  420. if (btn == 1'b1) begin
  421. state <= STATE_PRE_DEBOUNCE;
  422. counter <= 23'd0;
  423. end else begin
  424. state <= STATE_IDLE;
  425. btn_deb <= 1'b0;
  426. end
  427. end
  428. STATE_PRE_DEBOUNCE: begin
  429. if (btn == 1'b1 && counter < debounce_time) begin
  430. counter <= counter + 1;
  431. state <= STATE_PRE_DEBOUNCE;
  432. end else if (btn == 1'b1 && counter >= debounce_time) begin
  433. counter <= 23'd0;
  434. state <= STATE_DEBOUNCE;
  435. btn_deb <= 1'b1;
  436. end else begin
  437. state <= STATE_IDLE;
  438. btn_deb <= 1'b0;
  439. end
  440. end
  441. STATE_DEBOUNCE: begin
  442. if (btn == 1'b1) begin
  443. state <= STATE_DEBOUNCE;
  444. btn_deb <= 1'b1;
  445. end else begin
  446. state <= STATE_IDLE;
  447. btn_deb <= 1'b0;
  448. end
  449. end
  450. default: begin
  451. state <= STATE_IDLE;
  452. btn_deb <= 1'b0;
  453. end
  454. endcase
  455. end
  456. end
  457. endmodule


 

testbench代码:

  1. `timescale 1ms/10us
  2. `define CLK_CYCLE 0.02
  3. module tb_washing;
  4. reg Clk ;
  5. reg Rst ;
  6. reg Mode ;
  7. reg Sta_Pause;
  8. wire Led_wash ;
  9. wire Led_rinse;
  10. wire Led_dry ;
  11. wire Beep;
  12. wire Roll_neg ;
  13. wire Roll_pos;
  14. wire [3:0] seg_sel ;
  15. wire [6:0] seg_led ;
  16. washing_machine u1(
  17. . Clk (Clk),
  18. . Rst (Rst),
  19. . Mode (Mode),
  20. . Sta_Pause (Sta_Pause),
  21. . Led_wash (Led_wash),
  22. . Led_rinse (Led_rinse),
  23. . Led_dry (Led_dry),
  24. . Beep (Beep),
  25. . Roll_neg (Roll_neg),
  26. . Roll_pos (Roll_pos),
  27. . seg_sel (seg_sel),
  28. . seg_led (seg_led)
  29. );
  30. initial begin
  31. Clk = 1'b0;
  32. Rst = 1'b0;
  33. Mode = 1'b0;
  34. Sta_Pause = 1'b0;
  35. #300
  36. Rst = 1'b1;
  37. #100
  38. repeat (2) @(posedge Clk);
  39. Mode = 1'b1;
  40. #400
  41. Mode = 1'b0;
  42. #400
  43. Mode = 1'b1;
  44. #0.1
  45. Mode = 1'b0;
  46. #0.1
  47. Mode = 1'b1;
  48. #400
  49. Mode = 1'b0;
  50. #400
  51. Mode = 1'b1;
  52. #400
  53. Mode = 1'b0;
  54. #400
  55. Mode = 1'b1;
  56. #400
  57. Mode = 1'b0;
  58. #400
  59. Sta_Pause = 1'b1;
  60. #0.1
  61. Sta_Pause = 1'b0;
  62. #0.1
  63. Sta_Pause = 1'b1;
  64. #400
  65. Sta_Pause = 1'b0;
  66. @(posedge Led_rinse);
  67. Sta_Pause = 1'b1;
  68. #400
  69. Sta_Pause = 1'b0;
  70. #4000
  71. Sta_Pause = 1'b1;
  72. #400
  73. Sta_Pause = 1'b0;
  74. #100000
  75. $finish;
  76. end
  77. always #(`CLK_CYCLE / 2) Clk = ~Clk;
  78. endmodule


仿真结果:

开始转动前:

开始转动后:

板级验证:

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小桥流水78/article/detail/771907
推荐阅读
相关标签
  

闽ICP备14008679号