赞
踩
简单的练习一下,题目要求如下:
代码如下:
LCD12864:
-
- module lcd12864_drive
- (
- input clock,
- input reset,
- input [63:0] data_buf,
- output lcd12864_rs,
- output lcd12864_rw,
- output lcd12864_en,
- output [7:0] lcd12864_data
- );
-
-
- wire [63:0] data_buf;
-
-
- /**************************产生lcd12864时钟信号*************************/
-
- reg clk_lcd12864;
- reg [19:0]cnt;
- always @(posedge clock or posedge reset)
- begin
- if (reset)
- begin
- cnt <= 20'b0;
- clk_lcd12864 <= 0;
- end
- else if(cnt == 20'd20000) //时钟频率非常重要!!将近3k,经实测5k会在第0位出错。
- begin
- cnt <= 20'd0;
- clk_lcd12864 <= ~clk_lcd12864;
- end
- else
- cnt <= cnt +1'b1;
- end
-
-
- reg [1:0] clk_lcd12864_sync;
- always @(posedge clock or posedge reset)
- begin
- if (reset)
- clk_lcd12864_sync <= 2'b00;
- else
- clk_lcd12864_sync <= {clk_lcd12864_sync[0],clk_lcd12864};
- end
-
- assign clk_lcd12864_pos = (clk_lcd12864_sync == 2'b01);
-
-
- //****************************lcd12864控制信号*****************************************/
- reg [8:0] state; //State Machine code
- parameter IDLE = 4'd0;
- parameter CMD_WIDTH = 4'd1; //设置数据接口数量
- parameter CMD_SET = 4'd2; //选择指令集
- parameter CMD_CURSOR = 4'd3; //设置光标
- parameter CMD_CLEAR = 4'd4; //清屏
- parameter CMD_ACCESS = 4'd5; //输入方式设置:数据读写操作后,地址自动加一/画面不动
- parameter CMD_DDRAM = 4'd6; //DDRAM行地址
- parameter DATA_WRITE = 4'd7; //数据写入
- parameter STOP = 4'd8; //
-
- reg lcd12864_rs_r;
- reg [7:0] lcd12864_data_r;
- reg [7:0] data_buff;
-
- reg [5:0] cnt_time;
-
- //输出管教配置
- assign lcd12864_rs = lcd12864_rs_r;
- assign lcd12864_rw = 1'b0;
- assign lcd12864_en = clk_lcd12864_sync[1]; //与lcd12864时钟相同
- assign lcd12864_data = lcd12864_data_r;
-
-
- always @(posedge clock or posedge reset)
- begin
- if(reset)
- begin
- lcd12864_rs_r <= 1'b0;
- state <= IDLE;
- // lcd12864_data_r <= 8'bzzzzzzzz; //高阻态
- lcd12864_data_r <= 8'b11111111; //高阻态
- cnt_time <= 6'd0;
- end
- else if(clk_lcd12864_pos)
- begin
- case(state)
- IDLE:
- begin
- lcd12864_rs_r <= 1'b0;
- cnt_time <= 6'd0;
- state <= CMD_WIDTH;
- // lcd12864_data_r <= 8'bzzzzzzzz;
- lcd12864_data_r <= 8'b11111111;
-
- end
- CMD_WIDTH:
- begin
- lcd12864_rs_r <= 1'b0;
- state <= CMD_SET;
- lcd12864_data_r <= 8'h30; //8位数据口
- end
- CMD_SET:
- begin
- lcd12864_rs_r <= 1'b0;
- state <= CMD_CURSOR;
- lcd12864_data_r <= 8'h30; //基本指令集
- end
- CMD_CURSOR:
- begin
- lcd12864_rs_r <= 1'b0;
- state <= CMD_CLEAR;
- lcd12864_data_r <= 8'h0c; // 关光标
- end
- CMD_CLEAR:
- begin
- lcd12864_rs_r <= 1'b0;
- state <= CMD_ACCESS;
- lcd12864_data_r <= 8'h01; //清屏
- end
- CMD_ACCESS:
- begin
- lcd12864_rs_r <= 1'b0;
- state <= CMD_DDRAM;
- lcd12864_data_r <= 8'h06; //进入点设定
- end
- CMD_DDRAM: //行数命令
- begin
- lcd12864_rs_r <= 1'b0;
- state <= DATA_WRITE;
- case (cnt_time)
- 6'd0: lcd12864_data_r <= 8'h80;
- 6'd16: lcd12864_data_r <= 8'h90;
- 6'd32: lcd12864_data_r <= 8'h88;
- 6'd48: lcd12864_data_r <= 8'h98;
- endcase
- end
- DATA_WRITE: //写数据
- begin
- lcd12864_rs_r <= 1'b1;
- cnt_time <= cnt_time + 1'b1;
- lcd12864_data_r <= data_buff;
- case (cnt_time)
- 6'd15: state <= CMD_DDRAM;
- 6'd31: state <= CMD_DDRAM;
- 6'd47: state <= CMD_DDRAM;
- 6'd63: state <= STOP;
- default: state <= DATA_WRITE;
- endcase
- end
- STOP:
- begin
- lcd12864_rs_r <= 1'b0;
- state <= CMD_DDRAM;
- lcd12864_data_r <= 8'h80; //从第几行循环
- cnt_time <= 6'd0;
- end
- default:
- state <= IDLE;
- endcase
- end
- end
-
-
- always @(cnt_time)
- begin
- case (cnt_time)
- 6'd0: data_buff <= "W";
- 6'd1: data_buff <= ":";
- 6'd2: data_buff <= 8'h20;
- 6'd3: data_buff <= data_buf[15:8]+8'h30;//温湿度
- 6'd4: data_buff <= 8'h20;
- 6'd5: data_buff <= 8'h20;
- 6'd6: data_buff <= data_buf[7:0]+8'h30;
- 6'd7: data_buff <= 8'h20;
- 6'd8: data_buff <= 8'h20;
- 6'd9: data_buff <= "S";
- 6'd10: data_buff <= ":";
- 6'd11: data_buff <= 8'h20;
- 6'd12: data_buff <= data_buf[31:24]+8'h30;
- 6'd13: data_buff <= 8'h20;
- 6'd14: data_buff <= 8'h20;
- 6'd15: data_buff <= data_buf[23:16]+8'h30;
- 6'd16: data_buff <= 8'h20;//下一行开头
- 6'd17: data_buff <= 8'h20;
- 6'd18: data_buff <= data_buf[63:56]+8'h30;//速度
- 6'd19: data_buff <= 8'h20;
- 6'd20: data_buff <= data_buf[55:48]+8'h30;
- 6'd21: data_buff <= 8'h20;
- 6'd22: data_buff <= data_buf[47:40]+8'h30;
- 6'd23: data_buff <= 8'h20;
- 6'd24: data_buff <= data_buf[39:32]+8'h30;
- 6'd25: data_buff <= 8'h20;
- 6'd26: data_buff <= 8'h20;
- 6'd27: data_buff <= 8'h20;//数字0
- 6'd28: data_buff <= 8'h20;//数字1
- 6'd29: data_buff <= 8'h20;//数字2
- 6'd30: data_buff <= 8'h20;
- 6'd31: data_buff <= 8'h20;
-
- 6'd32: data_buff <= 8'h20;
- 6'd33: data_buff <= 8'h20;
- 6'd34: data_buff <= 8'h20;
- 6'd35: data_buff <= 8'h20;
- 6'd36: data_buff <= 8'h20;
- 6'd37: data_buff <= 8'h20;
- 6'd38: data_buff <= 8'h20;
- 6'd39: data_buff <= 8'h20;
- 6'd40: data_buff <= 8'h20;
- 6'd41: data_buff <= 8'h20;
- 6'd42: data_buff <= 8'h20;
- 6'd43: data_buff <= 8'h20;
- 6'd44: data_buff <= 8'h20;
- 6'd45: data_buff <= 8'h20;
- 6'd46: data_buff <= 8'h20;
- 6'd47: data_buff <= 8'h20;
-
- 6'd48: data_buff <= 8'h20;
- 6'd49: data_buff <= 8'h20;
- 6'd50: data_buff <= 8'h20;
- 6'd51: data_buff <= 8'h20;
- 6'd52: data_buff <= 8'h20;
- 6'd53: data_buff <= 8'h20;
- 6'd54: data_buff <= 8'h20;
- 6'd55: data_buff <= 8'h20;
- 6'd56: data_buff <= 8'h20;
- 6'd57: data_buff <= 8'h20;
- 6'd58: data_buff <= 8'h20;
- 6'd59: data_buff <= 8'h20;
- 6'd60: data_buff <= 8'h20;
- 6'd61: data_buff <= 8'h20;
- 6'd62: data_buff <= 8'h20;
- 6'd63: data_buff <= 8'h20;
-
- default : data_buff <= 8'h02;
- endcase
- end
-
-
- endmodule
button:
-
- module button
- (
- input clock,
- input reset,
- input [3:0] row, //行
- output [3:0] col, //列
- output [3:0] key_value,
-
- output key_out_flag
- );
-
-
- reg [3:0] col;
- reg [3:0] key_value;
- reg [31:0] count;
- wire clk_20ms_flag;
- reg [2:0] state; //状态标志
- reg key_flag; //按键标志位
- reg key_out_flag;
- reg [3:0] col_reg; //寄存扫描列值
- reg [3:0] row_reg; //寄存扫描行值
-
-
- always @(posedge clock or posedge reset)
- begin
- if(reset)
- count <= 0;
- else
- count <= count + 1;
- end
-
-
- assign clk_20ms_flag = (count[20:0] == 21'd2000000);
-
-
-
- always @(posedge clock or posedge reset)
- begin
- if(reset)
- begin
- col <= 4'b0000;
- state <= 0;
- end
- else if(clk_20ms_flag)
- case (state)
- 0:
- begin
- col[3:0] <= 4'b0000;
- key_flag <= 1'b0;
-
- if(row[3:0] != 4'b1111)
- begin
- state <= 1;
- col[3:0] <= 4'b1110;
- end //有键按下,扫描第一行
-
- else
- state <= 0;
-
- end
-
- 1:
- begin
- if(row[3:0] != 4'b1111)
- state <= 5;//判断是否是第一行
- else
- begin
- state <= 2;
- col[3:0] <= 4'b1101;
- end //扫描第二行
- end
-
- 2:
- begin
- if(row[3:0] != 4'b1111)
- state <= 5;//判断是否是第二行
- else
- begin
- state <= 3;
- col[3:0] <= 4'b1011;
- end //扫描第三行
-
- end
-
- 3:
- begin
- if(row[3:0] != 4'b1111)
- state <= 5; //判断是否是第三一行
- else
- begin
- state <= 4;
- col[3:0] <= 4'b0111;
- end //扫描第四行
- end
-
- 4:
- begin
- if(row[3:0] != 4'b1111)
- state <= 5;//判断是否是第一行
-
- else
- state <= 0;
- end
-
- 5:
- begin
- if(row[3:0] != 4'b1111)
- begin
- col_reg <= col; //保存扫描列值
- row_reg <= row; //保存扫描行值
- state <= 5;
- key_flag <= 1'b1; //有键按下
- end
- else
- state <= 0;
- end
-
- endcase
-
- end
-
-
-
- always @(clock or col_reg or row_reg)
- begin
- if(key_flag == 1'b1)
- begin
- key_out_flag <= 1;
- case ({col_reg,row_reg})
- 8'b1110_1110:key_value <= 4'b0001 ;
- 8'b1101_1110:key_value <= 4'b0010;
- 8'b1011_1110:key_value <= 4'b0110;
- 8'b0111_1110:key_value <= 4'b0000;
- // 8'b1110_1101:key_value <= 4;
- // 8'b1101_1101:key_value <= 5;
- // 8'b1011_1101:key_value <= 6;
- // 8'b0111_1101:key_value <= 7;
- // 8'b1110_1011:key_value <= 8;
- // 8'b1101_1011:key_value <= 9;
- // 8'b1011_1011:key_value <= 10;
- // 8'b0111_1011:key_value <= 11;
- // 8'b1110_0111:key_value <= 12;
- // 8'b1101_0111:key_value <= 13;
- // 8'b1011_0111:key_value <= 14;
- // 8'b0111_0111:key_value <= 15;
- default: key_value <= 4'b0000;
- endcase
- end
- else
- key_out_flag <= 0;
- end
-
- endmodule
speed:
- module speed
- (
- input clock,
- input reset,
- input pulse_from_motor,
- output [19:0] speed_value
- );
-
-
- reg [32:0] cnt;
- always @(posedge clock or posedge reset)
- begin
- if (reset)
- cnt <= 0;
- // else if(cnt == 33'd6000000000)
- else if(cnt == 33'd300000000)
- cnt <= 0;
- else
- cnt <= cnt + 1'b1;
- end
-
- wire start_flag;
- wire end_flag;
- assign start_flag = (cnt <= 33'd5);
- //assign end_flag = (cnt == 33'd6000000000);
- assign end_flag = (cnt == 33'd300000000);
-
- reg [1:0] pulse_from_motor_sync;
- always @(posedge clock or posedge reset)
- begin
- if (reset)
- pulse_from_motor_sync <= 2'b00;
- else
- pulse_from_motor_sync <= {pulse_from_motor_sync[0],pulse_from_motor};
- end
-
- wire pulse_from_motor_pos;
- assign pulse_from_motor_pos = (pulse_from_motor_sync == 2'b01);
-
- wire [23 : 0] Q;
- c_counter_binary_0 c_counter_binary_0_0
- (
- .CLK(clock), // input wire CLK
- .CE(pulse_from_motor_pos), // input wire CE
- .SCLR(start_flag), // input wire SCLR
- .Q(Q) // output wire [23 : 0] Q
- );
-
- reg [23:0] pulse_cnt;
- always @(posedge clock or posedge reset)
- begin
- if (reset)
- pulse_cnt <= 0;
- else if(end_flag)
- pulse_cnt <= Q;
- else
- ;
- end
-
- wire [15:0] turns_num;
- //assign turns_num = pulse_cnt / 20;
- assign turns_num = pulse_cnt[15:0];
-
- assign speed_value [3:0] = turns_num % 10;
- assign speed_value [7:4] = turns_num % 100 / 10;
- assign speed_value [11:8] = turns_num % 1000 / 100;
- assign speed_value [15:12] = turns_num % 10000 / 1000;
- assign speed_value [19:16] = turns_num % 100000 / 10000;
-
- endmodule
dht:
-
- module dht11_drive
- (
- input clock,
- input reset,
- inout dht11,
- output reg [31:0] dht11_value,
- output [7:0] dht11_value_sd,
- output [7:0] dht11_value_wd
- );
-
-
- parameter POWER_ON_NUM = 1000_000; //上电延时1s
- parameter st_power_on_wait = 3'd0; //上电延时等待
- parameter st_low_20ms = 3'd1; //主机发送20ms低电平
- parameter st_high_13us = 3'd2; //主机释放总线13us
- parameter st_rec_low_83us = 3'd3; //接收83us低电平响应
- parameter st_rec_high_87us = 3'd4; //等待87us高电平(准备接收数据)
- parameter st_rec_data = 3'd5; //接收40位数据
- parameter st_delay = 3'd6; //延时等待,延时完成后重新操作DHT11
-
-
- reg [2:0] cur_state; //当前状态
- reg [2:0] next_state; //下一个状态
-
- reg [5:0] clock_cnt; //分频计数器
- reg clock_1M; //1MHz时钟
- reg [20:0] us_cnt; //1微秒计数器
- reg us_cnt_clr; //1微秒计数器清零信号
- reg [39:0] data_temp; //缓存接收到的数据
- reg step; //数据采集状态
- reg [5:0] data_cnt; //接收数据用计数器
- reg dht11_buffer; //DHT11输出信号
-
- reg [1:0] clock_1M_sync;
- wire clock_1M_pos;
- wire clock_1M_neg;
-
- reg [1:0] dht11_sync;
- wire dht11_pos;
- wire dht11_neg;
-
-
- //1MHz分频时钟
- always @ (posedge clock or posedge reset)
- begin
- if (reset)
- clock_cnt <= 6'd0;
- else if (clock_cnt == 6'd49)
- clock_cnt <= 6'd0;
- else
- clock_cnt <= clock_cnt + 1'b1;
- end
-
- always @ (posedge clock or posedge reset)
- begin
- if (reset)
- clock_1M <= 1'b0;
- else if (clock_cnt == 6'd49)
- clock_1M <= ~ clock_1M;
- else
- clock_1M <= clock_1M;
- end
-
-
- always @ (posedge clock or posedge reset)
- begin
- if (reset)
- clock_1M_sync <= 2'b00;
- else
- clock_1M_sync <= {clock_1M_sync[0],clock_1M};
- end
-
- assign clock_1M_pos = (clock_1M_sync == 2'b01);
- assign clock_1M_neg = (clock_1M_sync == 2'b10);
-
-
- always @ (posedge clock or posedge reset)
- begin
- if (reset)
- dht11_sync <= 2'b11;
- else if(clock_1M_pos)
- dht11_sync <= {dht11_sync[0],dht11};
- end
-
- assign dht11_pos = (dht11_sync == 2'b01);
- assign dht11_neg = (dht11_sync == 2'b10);
-
-
- //us计数器
- always @ (posedge clock or posedge reset)
- begin
- if (reset)
- us_cnt <= 21'd0;
- else if (us_cnt_clr)
- us_cnt <= 21'd0;
- else if(clock_1M_pos)
- us_cnt <= us_cnt + 1'b1;
- end
-
- //状态跳转
- always @ (posedge clock or posedge reset)
- begin
- if (reset)
- cur_state <= st_power_on_wait;
- else
- cur_state <= next_state;
- end
-
- //状态机读取DHT11数据
- always @ (posedge clock or posedge reset)
- begin
- if(reset)
- begin
- next_state <= st_power_on_wait;
- data_temp <= 40'd0;
- step <= 1'b0;
- us_cnt_clr <= 1'b0;
- data_cnt <= 6'd0;
- dht11_buffer <= 1'bz;
- end
- else if(clock_1M_pos)
- begin
- case (cur_state)
- st_power_on_wait :
- begin
- if(us_cnt < POWER_ON_NUM)
- begin
- dht11_buffer <= 1'bz;
- us_cnt_clr <= 1'b0;
- end
- else
- begin
- next_state <= st_low_20ms;
- us_cnt_clr <= 1'b1;
- end
- end
-
- st_low_20ms :
- begin
- if(us_cnt < 20000)
- begin
- dht11_buffer <= 1'b0;
- us_cnt_clr <= 1'b0;
- end
- else
- begin
- dht11_buffer <= 1'bz;
- next_state <= st_high_13us;
- us_cnt_clr <= 1'b1;
- end
- end
-
- st_high_13us :
- begin
- if (us_cnt < 20)
- begin
- us_cnt_clr <= 1'b0;
- if(dht11_neg)
- begin
- next_state <= st_rec_low_83us;
- us_cnt_clr <= 1'b1;
- end
- end
- else
- next_state <= st_delay;
- end
-
- st_rec_low_83us :
- begin
- if(dht11_pos)
- next_state <= st_rec_high_87us;
- end
-
- st_rec_high_87us :
- begin
- if(dht11_neg)
- begin
- next_state <= st_rec_data;
- us_cnt_clr <= 1'b1;
- end
- else
- begin
- data_cnt <= 6'd0;
- data_temp <= 40'd0;
- step <= 1'b0;
- end
- end
-
- st_rec_data :
- begin
- case(step)
- 0 :
- begin
- if(dht11_pos)
- begin
- step <= 1'b1;
- us_cnt_clr <= 1'b1;
- end
- else
- us_cnt_clr <= 1'b0;
- end
- 1 :
- begin
- if(dht11_neg)
- begin
- data_cnt <= data_cnt + 1'b1;
- if(us_cnt < 60)
- data_temp <= {data_temp[38:0],1'b0};
- else
- data_temp <= {data_temp[38:0],1'b1};
-
- step <= 1'b0;
- us_cnt_clr <= 1'b1;
- end
- else
- us_cnt_clr <= 1'b0;
- end
- endcase
-
- if(data_cnt == 40)
- begin
- next_state <= st_delay;
- if(data_temp[7:0] == data_temp[39:32] + data_temp[31:24] + data_temp[23:16] + data_temp[15:8])
- dht11_value <= data_temp[39:8];
- end
- end
-
- st_delay :
- begin
- if(us_cnt < 2000_000)
- us_cnt_clr <= 1'b0;
- else
- begin
- next_state <= st_low_20ms;
- us_cnt_clr <= 1'b1;
- end
- end
- default : ;
- endcase
- end
- end
-
- assign dht11 = dht11_buffer;
-
- assign dht11_value_sd[3:0] = dht11_value[31:24] % 10;
- assign dht11_value_sd[7:4] = dht11_value[31:24] / 10;
-
- assign dht11_value_wd[3:0] = dht11_value[15:8] % 10;
- assign dht11_value_wd[7:4] = dht11_value[15:8] / 10;
-
- endmodule
Judge:(电机驱动,这里用的是步进电机)
-
- module Judge(
- input clk,
- input rst,
- input key_out_flag,
- input [7:0]t_data,//温度
- input [7:0]s_data,//湿度
- input A,//清零
- input B,//手动模式
- input C,//速度变档
- input D,//恢复到自动模式
- output [3:0] motor_en
- );
- reg [3:0] motor_en_reg;
- reg [31:0] cnt;
- reg [1:0] s;
- reg [1:0] state_speed;
- always@(posedge key_out_flag)
- begin
- if(rst||A)
- begin
- s<=0;
- end
- else
- begin
- if(C)
- s<=s+1;
- end
- end
-
- always@(posedge clk)
- begin
- if(rst)
- begin
- state_speed<=cnt[21:20];
- end
- else
- begin
- case(s)
- 2'b00:
- state_speed<=cnt[21:20];
- 2'b01:
- state_speed<=cnt[20:19];
- 2'b10:
- state_speed<=cnt[19:18];
- 2'b11:
- state_speed<=cnt[18:17];//由于频率过快,该状态会强制暂停
- default:;
- endcase
- end
- end
-
-
- always@(posedge clk)
- begin
- if(rst||A)
- begin
- motor_en_reg<=0;
- end
- else if(B)//手动模式
- begin
- case (state_speed)
- 2'b00 :
- motor_en_reg <= 4'b0001;
- 2'b01 :
- motor_en_reg <= 4'b0010;
- 2'b10 :
- motor_en_reg <= 4'b0100;
- 2'b11 :
- motor_en_reg <= 4'b1000;
- endcase
- end
- else if(s_data[7:4]<4'd3)//湿度小于三十度
- begin
- case (cnt[19:18])
- 2'b00 :
- motor_en_reg <= 4'b0001;
- 2'b01 :
- motor_en_reg <= 4'b0010;
- 2'b10 :
- motor_en_reg <= 4'b0100;
- 2'b11 :
- motor_en_reg <= 4'b1000;
- endcase
- end
- else
- begin
- case (cnt[21:20])
- 2'b00 :
- motor_en_reg <= 4'b0001;
- 2'b01 :
- motor_en_reg <= 4'b0010;
- 2'b10 :
- motor_en_reg <= 4'b0100;
- 2'b11 :
- motor_en_reg <= 4'b1000;
- endcase
- end
- end
-
-
- always @(posedge clk )
- begin
- if (rst)
- cnt <= 0;
- else
- cnt <= cnt + 1'b1;
- end
- assign motor_en = motor_en_reg;
- endmodule
实验效果:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。