共7条
1/1 1 跳转至页
交一下PCF8563的作业
/****************************************************************************** *Engineer: superdian *Create Date: 2014/9/7 *Design Name: *Module Name: pcf8563_topd *Project Name: *Target Devices: EP3CE5E144C8 *Tool versions: *Description: * *Dependencies: * *Revision: *Revision 0.01 - File Created *Additional Comments: 开发板晶振为20MHZ,工程中通过倍频50MH。 ******************************************************************************/ module pcf8563_top( input sys_rstn, input sys_clk, output scl, inout wire sda, output lcd_rs , //lcd的寄存器选择输出信号 output lcd_rw , //lcd的读、写操作选择输出信号 output lcd_en , //lcd使能信号 output [7:0] lcd_data //lcd的数据总线(不进行读操作,故为输出) ); wire clk; wire [7:0] data_trans; //从相应寄存器读取的数据 wire finish_bit; //从单个寄存器读取数据完毕的标志 reg [7:0] data_word; //发送相应寄存器地址 reg [7:0] sec; //储存从秒寄存器读出的数据 reg [7:0] mnt; //储存从分寄存器读出的数据 reg [7:0] hur; //储存从小时寄存器读出的数据 reg [7:0] week; //储存从星期寄存器读出的数据 reg [7:0] day; //储存从日寄存器读出的数据 reg [7:0] month; //储存从月份寄存器读出的数据 reg [7:0] year; //储存从年寄存器读出的数据 reg [7:0] code_ctl; //状态机状态寄存器 parameter sec_time=8'd0; parameter mnt_time=8'd1; parameter hour_time=8'd2; parameter day_time=8'd3; parameter week_time=8'd4; parameter month_time=8'd5; parameter year_time=8'd6; clk_pll clk_pll ( .inclk0(sys_clk), .c0(clk) ); i2c_test i2c_test( .clk(clk), .scl(scl), .sda(sda), .data_read_wire(data_trans), .sda_data_addr(8'ha2), .sda_data_word(data_word), .finish_bit(finish_bit) ); lcd1602 lcd1602( .sys_rstn(sys_rstn), .lcd_rs(lcd_rs), .lcd_rw(lcd_rw), .lcd_en(lcd_en), .lcd_data(lcd_data), .sys_clk(clk), .seg_sec(sec), .seg_mnt(mnt), .seg_hur(hur), .seg_week(week), .seg_day(day), .seg_month(month), .seg_year(year) ); always@(posedge clk) begin case(code_ctl) sec_time: begin if(finish_bit==1'b0) begin data_word<=8'h02;//发送秒寄存器地址 sec<=data_trans; end else begin code_ctl<=mnt_time; end end mnt_time: begin if(finish_bit==1'b0) begin data_word<=8'h03;//发送分钟寄存器地址 mnt<=data_trans; end else begin code_ctl<=hour_time; end end hour_time: begin if(finish_bit==1'b0) begin data_word<=8'h04;//发送小时寄存器地址 hur<=data_trans; end else begin code_ctl<=day_time; end end day_time: begin if(finish_bit==1'b0) begin data_word<=8'h05;//发送日寄存器地址 day<=data_trans; end else begin code_ctl<=week_time; end end week_time: begin if(finish_bit==1'b0) begin data_word<=8'h6;//发送星期寄存器地址 week<=data_trans; end else begin code_ctl<=month_time; end end month_time: begin if(finish_bit==1'b0) begin data_word<=8'h07;//发送月寄存器地址 month<=data_trans; end else begin code_ctl<=year_time; end end year_time: begin if(finish_bit==1'b0) begin data_word<=8'h08;//发送年寄存器地址 year<=data_trans; end else begin code_ctl<=sec_time; end end endcase end endmodule
/****************************************************************************** *Engineer: superdian *Create Date: 2014/9/7 *Design Name: *Module Name: lcd1602 *Project Name: *Target Devices: EP3CE5E144C8 *Tool versions: *Description: * *Dependencies: * *Revision: *Revision 0.01 - File Created *Additional Comments: 开发板晶振为20MHZ,工程中通过倍频50MH。 ******************************************************************************/ module lcd1602(sys_clk , sys_rstn , lcd_rs , lcd_rw , lcd_en , lcd_data , seg_sec , seg_mnt , seg_hur , seg_week , seg_day , seg_month , seg_year ); //输入输出信号定义 input [7:0] seg_sec; input [7:0] seg_mnt; input [7:0] seg_hur; input [7:0] seg_week; input [7:0] seg_day; input [7:0] seg_month; input [7:0] seg_year; input sys_clk ;//系统时钟输入 input sys_rstn ;//系统复位信号,低电平有效 output lcd_rs ;//lcd的寄存器选择输出信号 output lcd_rw ;//lcd的读、写操作选择输出信号 output lcd_en ;//lcd使能信号 output [7:0] lcd_data ;//lcd的数据总线(不进行读操作,故为输出) //寄存器定义 reg lcd_rs ; reg clk_div ; reg [17:0] delay_cnt ; reg [7:0] lcd_data ; reg [5:0] char_cnt ; reg [7:0] data_disp ; reg [9:0] state ; /******************************** *********************************/ reg [3:0] disp_dat; reg [25:0] g=0; reg [3:0] shi1; reg [1:0] shi2; reg [3:0] fen1; reg [2:0] fen2; reg [3:0] miao1; reg [2:0] miao2; reg [7:0] shi11; reg [7:0] shi22; reg [7:0] fen11; reg [7:0] fen22; reg [7:0] miao11; reg [7:0] miao22; reg [2:0] week1; reg [3:0] day1; reg [2:0] day2; reg [3:0] month1; reg [3:0] month2; reg [3:0] year1; reg [3:0] year2; reg [7:0] week11; reg [7:0] day11; reg [7:0] day22; reg [7:0] month11; reg [7:0] month22; reg [7:0] year11; reg [7:0] year22; reg [7:0] centry1; reg [7:0] centry2; reg centry; parameter idle = 10'b000000000, //初始状态,下一个状态为CLEAR clear = 10'b000000001, //清屏 set_function = 10'b000000010, //功能设置:8位数据接口/2行显示/5*8点阵字符 switch_mode = 10'b000000100, //显示开关控制:开显示,光标和闪烁关闭 set_mode = 10'b000001000, //输入方式设置:数据读写操作后,地址自动加一/画面不动 shift = 10'b000010000, //光标、画面位移设置:光标向左平移一个字符位(光标显示是关闭的,所以实际上设置是看不出效果的) set_ddram1 = 10'b000100000, //设置DDRAM的地址:第一行起始为0x00(注意输出时DB7一定要为1) set_ddram2 = 10'b001000000, //设置DDRAM的地址:第二行为0x40(注意输出时DB7一定要为1) write_ram1 = 10'b010000000, //数据写入DDRAM相应的地址 write_ram2 = 10'b100000000; //数据写入DDRAM相应的地址 assign lcd_rw = 1'b0; //没有读操作,R/W信号始终为低电平 assign lcd_en = clk_div; //E信号出现高电平以及下降沿的时刻与LCD时钟相同 //时钟分频 always@(posedge sys_clk or negedge sys_rstn) begin if(!sys_rstn) begin delay_cnt<=18'd0; clk_div<=1'b0; end else if(delay_cnt==18'd249999)//原来50MHZ249999 begin delay_cnt<=18'd0; clk_div<=~clk_div; end else begin delay_cnt<=delay_cnt+1'b1; clk_div<=clk_div; end end always@(posedge clk_div or negedge sys_rstn) //State Machine begin if(!sys_rstn) begin state <= idle; lcd_data <= 8'bzzzzzzzz; char_cnt <= 5'd0; end else begin case(state) idle: begin //初始状态 state <= clear; lcd_data <= 8'bzzzzzzzz; end clear: begin //清屏 state <= set_function; lcd_rs<=1'b0; lcd_data <= 8'b00000001; end set_function: //功能设置(38H):8位数据接口/2行显示/5*8点阵字符 begin state <= switch_mode; lcd_rs<=1'b0; lcd_data <= 8'b00111000; end switch_mode: //显示开关控制(0CH):开显示,光标和闪烁关闭 begin state <= set_mode; lcd_rs<=1'b0; lcd_data <= 8'b00001100; end set_mode:begin //输入方式设置(06H):数据读写操作后,地址自动加一/画面不动 state <= shift; lcd_rs<=1'b0; lcd_data <= 8'b00000110; end shift: begin //光标、画面位移设置(10H):光标向左平移一个字符位(光标显示是关闭的,所以实际上设置是看不出效果的) state <= set_ddram1; lcd_rs<=1'b0; lcd_data <= 8'b0001_0000; end set_ddram1: //设置DDRAM的地址:第一行起始为00H(注意输出时DB7一定要为1) begin state <= write_ram1; lcd_rs<=1'b0; lcd_data <= 8'b1000_0000;//Line1 end set_ddram2: //设置DDRAM的地址:第二行为40H(注意输出时DB7一定要为1) begin state <= write_ram2; lcd_rs<=1'b0; lcd_data <= 8'b1100_0000;//Line2 end write_ram1: begin if(char_cnt <=5'd15) begin char_cnt <= char_cnt + 1'b1; lcd_rs<=1'b1; lcd_data <= data_disp; state <= write_ram1; end else begin state <= set_ddram2; end end write_ram2: begin if(char_cnt <=5'd31) begin char_cnt <= char_cnt + 1'b1; lcd_rs<=1'b1; lcd_data <= data_disp; state <= write_ram2; end else begin char_cnt <=5'd0; state <= shift; end end default: state <= idle; endcase end end always @(char_cnt) //输出的字符 begin case (char_cnt) 6'd0: data_disp = "-"; 6'd1: data_disp = "-"; 6'd2: data_disp = "-"; 6'd3: data_disp = "-"; 6'd4: data_disp = centry2; 6'd5: data_disp = centry1; 6'd6: data_disp = year22; 6'd7: data_disp = year11; 6'd8: data_disp = "/"; 6'd9: data_disp = month22; 6'd10: data_disp = month11; 6'd11: data_disp = "/"; 6'd12: data_disp = day22; 6'd13: data_disp = day11; 6'd14: data_disp = "/"; 6'd15: data_disp = week11; 6'd16: data_disp = "E"; 6'd17: data_disp = "E"; 6'd18: data_disp = "P"; 6'd19: data_disp = "W"; 6'd20: data_disp = "-"; 6'd21: data_disp = "-"; 6'd22: data_disp = "-"; 6'd23: data_disp = "-"; 6'd24: data_disp = shi22; 6'd25: data_disp = shi11; 6'd26: data_disp = "/"; 6'd27: data_disp = fen22; 6'd28: data_disp = fen11; 6'd29: data_disp = "/"; 6'd30: data_disp = miao22; 6'd31: data_disp = miao11; default : data_disp ="-"; endcase end /*************************************************** 将从pcf8563读出的数据写入相应时,分,秒,年,月,日寄存器 *****************************************************/ always@(posedge sys_clk) begin if(g==26'd2499999) g<=26'd0; else g<=g+1'b1; end always@(posedge sys_clk) begin if(g==26'd2499999) disp_dat<=disp_dat+1'b1; else disp_dat<=disp_dat; end always@(disp_dat) begin case(disp_dat) 4'd0: miao1=seg_sec[3:0]; 4'd1: miao2=seg_sec[6:4]; 4'd2: fen1=seg_mnt[3:0]; 4'd3: fen2=seg_mnt[6:4]; 4'd4: shi1=seg_hur[3:0]; 4'd5: shi2=seg_hur[5:4]; 4'd6: week1=seg_week[2:0]; 4'd7: day1=seg_day[3:0]; 4'd8: day2=seg_day[5:4]; 4'd9: month1=seg_month[3:0]; 4'd10: month2=seg_month[5]; 4'd11: year1=seg_year[3:0]; 4'd12: year2=seg_year[7:4]; 4'd13: centry=seg_month[7]; endcase end always@(posedge sys_clk) begin if(centry == 1'b0) begin centry1 <= "0"; centry2 <= "2"; end else begin centry1 <= "9"; centry2 <= "1"; end end /************************************************* 将相应寄存器的BCD码转换为ASCII码 **************************************************/ always@(week1) begin case(week1) 3'd0: week11 = "0"; 3'd1: week11 = "1"; 3'd2: week11 = "2"; 3'd3: week11 = "3"; 3'd4: week11 = "4"; 3'd5: week11 = "5"; 3'd6: week11 = "6"; 3'd7: week11 = "7"; default : week11 = "0"; endcase end always@(day1) begin case(day1) 4'd0: day11 = "0"; 4'd1: day11 = "1"; 4'd2: day11 = "2"; 4'd3: day11 = "3"; 4'd4: day11 = "4"; 4'd5: day11 = "5"; 4'd6: day11 = "6"; 4'd7: day11 = "7"; default: day11 = "0"; endcase end always@(day2) begin case(day22) 3'd0:day22 = "0"; 3'd1:day22 = "1"; 3'd2:day22 = "2"; 3'd3:day22 = "3"; default: day22 ="0"; endcase end always@(month1) begin case(month1) 4'd0: month11 = "0"; 4'd1: month11 = "1"; 4'd2: month11 = "2"; 4'd3: month11 = "3"; 4'd4: month11 = "4"; 4'd5: month11 = "5"; 4'd6: month11 = "6"; 4'd7: month11 = "7"; 4'd8: month11 = "8"; 4'd9: month11 = "9"; default : month11 = "0"; endcase end always@(month2) begin case(month2) 1'b0: month22 = "0"; 1'b1: month22 = "1"; default : month22 = "0"; endcase end always@(year1) begin case(year1) 4'd0: year11 = "0"; 4'd1: year11 = "1"; 4'd2: year11 = "2"; 4'd3: year11 = "3"; 4'd4: year11 = "4"; 4'd5: year11 = "5"; 4'd6: year11 = "6"; 4'd7: year11 = "7"; 4'd8: year11 = "8"; 4'd9: year11 = "9"; default : year11 = "0"; endcase end always@(year2) begin case(year2) 4'd0: year22 = "0"; 4'd1: year22 = "1"; 4'd2: year22 = "2"; 4'd3: year22 = "3"; 4'd4: year22 = "4"; 4'd5: year22 = "5"; 4'd6: year22 = "6"; 4'd7: year22 = "7"; 4'd8: year22 = "8"; 4'd9: year22 = "9"; default : year22 = "0"; endcase end always @(miao1) begin case (miao1) 4'd0: miao11 = "0"; 4'd1: miao11 = "1"; 4'd2: miao11 = "2"; 4'd3: miao11 = "3"; 4'd4: miao11 = "4"; 4'd5: miao11 = "5"; 4'd6: miao11 = "6"; 4'd7: miao11 = "7"; 4'd8: miao11 = "8"; 4'd9: miao11 = "9"; default : miao11 ="0"; endcase end always @(miao2) begin case (miao2) 3'd0: miao22 = "0"; 3'd1: miao22 = "1"; 3'd2: miao22 = "2"; 3'd3: miao22 = "3"; 3'd4: miao22 = "4"; 3'd5: miao22 = "5"; default : miao22 ="0"; endcase end always @(fen1) begin case (fen1) 4'd0: fen11 = "0"; 4'd1: fen11 = "1"; 4'd2: fen11 = "2"; 4'd3: fen11 = "3"; 4'd4: fen11 = "4"; 4'd5: fen11 = "5"; 4'd6: fen11 = "6"; 4'd7: fen11 = "7"; 4'd8: fen11 = "8"; 4'd9: fen11 = "9"; default : fen11 ="0"; endcase end always @(fen2) begin case (fen2) 3'd0: fen22 = "0"; 3'd1: fen22 = "1"; 3'd2: fen22 = "2"; 3'd3: fen22 = "3"; 3'd4: fen22 = "4"; 3'd5: fen22 = "5"; default : fen22 ="0"; endcase end always @(shi1) begin case (shi1) 4'd0: shi11 = "0"; 4'd1: shi11 = "1"; 4'd2: shi11 = "2"; 4'd3: shi11 = "3"; 4'd4: shi11 = "4"; 4'd5: shi11 = "5"; 4'd6: shi11 = "6"; 4'd7: shi11 = "7"; 4'd8: shi11 = "8"; 4'd9: shi11 = "9"; default : shi11 ="0"; endcase end always @(shi2) begin case (shi2) 2'd0: shi22 = "0"; 2'd1: shi22 = "1"; 2'd2: shi22= "2"; default : shi22 ="0"; endcase end endmodule
/****************************************************************************** *Engineer: superdian *Create Date: 2014/9/7 *Design Name: *Module Name: i2c_test *Project Name: *Target Devices: EP3CE5E144C8 *Tool versions: *Description: * *Dependencies: * *Revision: *Revision 0.01 - File Created *Additional Comments: 开发板晶振为20MHZ,工程中通过倍频50MHZ。 ******************************************************************************/ module i2c_test(input clk, output scl, inout wire sda, output [7:0]data_read_wire, input [7:0]sda_data_addr, input [7:0]sda_data_word, output reg finish_bit ); reg sda_io_flag; //sda输入输出状态寄存器 reg read_flag; //主机读写状态 reg sda_r; //数据寄存器 reg scl_r; //时钟脉冲寄存器 reg [7:0] scl_ctr; //scl分频参数寄存器 reg [7:0] scl_sts; reg [7:0] i2c_sts; reg [7:0] sda_data_a; reg [3:0] data_bit; reg [7:0] data_read; reg [24:0] timer; assign scl=scl_r; assign sda=sda_io_flag?sda_r:1'bz; //sda输入输出状态选择 assign data_read_wire=data_read; `define scl_pos (scl_sts==3'd0) `define scl_high (scl_sts==3'd1) `define scl_neg (scl_sts==3'd2) `define scl_low (scl_sts==3'd3) parameter idle =4'd0; parameter start =4'd1; parameter send_a =4'd2; parameter slv_ack1 =4'd3; parameter send_d =4'd4; parameter slv_ack2 =4'd5; parameter send_dd =4'd6; parameter slv_ack3 =4'd7; parameter read_byte =4'd8; parameter master_ack =4'd9; parameter stop =4'd10; //SCL分频250KHZ always@(posedge clk) begin if(scl_ctr ==8'd199) scl_ctr<=8'd0; else scl_ctr<=scl_ctr+1'b1; end always@(posedge clk) begin case(scl_ctr) 8'd49: scl_sts<=3'd1;//处于高电平中间用于数据采样 8'd99: scl_sts<=3'd2;//下降沿 8'd149: scl_sts<=3'd3;//处于低电平中间用于数据变化 8'd199: scl_sts<=3'd0;//上升沿 default: scl_sts<=3'd5; endcase end always@(posedge clk) begin if(scl_sts==3'd0) scl_r<=1'b1; if(scl_sts==3'd2) scl_r<=1'b0; end always@(posedge clk) begin if(timer==0) begin i2c_sts<=idle; data_bit<=4'd0; sda_io_flag<=1'b1; sda_r<=1'b1; read_flag<=1'b0; end case(i2c_sts) idle: begin i2c_sts<=start; if(read_flag==1'b1)//判断主机读写状态 sda_data_a<=sda_data_addr+1'b1;//地址+1,即为读状态(A3) else sda_data_a<=sda_data_addr;//地址不加一,即为写状态(A2) end start: begin if(`scl_high)//启动I2C begin sda_io_flag<=1'b1; sda_r<=1'b0; i2c_sts<=send_a;//发送地址状态 end else begin i2c_sts<=start; end end send_a://发送地址状态 begin if(`scl_low) begin case(data_bit)//8位串行地址数据 4'd0: sda_r<= sda_data_a[7]; 4'd1: sda_r<= sda_data_a[6]; 4'd2: sda_r<= sda_data_a[5]; 4'd3: sda_r<= sda_data_a[4]; 4'd4: sda_r<= sda_data_a[3]; 4'd5: sda_r<= sda_data_a[2]; 4'd6: sda_r<= sda_data_a[1]; 4'd7: sda_r<= sda_data_a[0]; endcase data_bit<=data_bit+1'b1; if(data_bit==4'd8)//发送地址完毕 begin sda_io_flag<=1'b0;//SDA做输入口 i2c_sts<=slv_ack1;//读从机应答信号 data_bit<=4'd0; end end else i2c_sts<=send_a; end slv_ack1://从机应答 begin if(`scl_high) begin sda_io_flag<=1'b0; if(sda==0) begin if(read_flag==1'b1) begin i2c_sts<=read_byte; sda_io_flag<=1'b0; end else begin i2c_sts<=send_d; sda_io_flag<=1'b1; sda_r<=1'b0; sda_data_a<=sda_data_word; end end end else begin i2c_sts<=slv_ack1; end end send_d://发送数据 begin if(`scl_low) begin case(data_bit) 4'd0: sda_r<=sda_data_a[7]; 4'd1: sda_r<=sda_data_a[6]; 4'd2: sda_r<=sda_data_a[5]; 4'd3: sda_r<=sda_data_a[4]; 4'd4: sda_r<=sda_data_a[3]; 4'd5: sda_r<=sda_data_a[2]; 4'd6: sda_r<=sda_data_a[1]; 4'd7: sda_r<=sda_data_a[0]; endcase data_bit<=data_bit+1'b1; if(data_bit==4'd8) begin sda_io_flag<=1'b0; i2c_sts<=slv_ack2;//发送数据完毕,进入应答状态 data_bit<=4'd0; end end else i2c_sts<=send_d; end slv_ack2://应答状态 begin if(`scl_high) begin sda_io_flag<=1'b0; if(sda==0) begin i2c_sts<=stop; sda_io_flag<=1'b1; sda_r<=1'b0; end end else begin i2c_sts<=slv_ack2; end end read_byte://读出数据 begin if(`scl_high) begin sda_io_flag<=1'b0; data_read<=(data_read<<1)|sda; data_bit<=data_bit+1'b1; if(data_bit==4'd7) begin i2c_sts<=master_ack; data_bit<=4'd0; end end end master_ack://主机应答 begin if(`scl_low) begin sda_io_flag<=1'b1; sda_r<=1'b0; data_bit<=data_bit+1'b1; if(data_bit==4'd1) begin i2c_sts<=stop; data_bit<=4'd0; end end end stop://停止I2C begin if(`scl_high) begin sda_r<=1'b1; read_flag<=1'b1; if(read_flag==1'b0) i2c_sts<=idle; else i2c_sts<=stop; end end endcase end always@(posedge clk) begin if(timer<=25'd12500000) begin timer<=timer+1'b1; if(timer==25'd12499999) finish_bit<=1'b1; end else begin timer<=25'd0; finish_bit<=1'b0; end end endmodule
共7条
1/1 1 跳转至页
回复
有奖活动 | |
---|---|
【有奖活动】分享技术经验,兑换京东卡 | |
话不多说,快进群! | |
请大声喊出:我要开发板! | |
【有奖活动】EEPW网站征稿正在进行时,欢迎踊跃投稿啦 | |
奖!发布技术笔记,技术评测贴换取您心仪的礼品 | |
打赏了!打赏了!打赏了! |
打赏帖 | |
---|---|
vscode+cmake搭建雅特力AT32L021开发环境被打赏30分 | |
【换取逻辑分析仪】自制底板并驱动ArduinoNanoRP2040ConnectLCD扩展板被打赏47分 | |
【分享评测,赢取加热台】RISC-V GCC 内嵌汇编使用被打赏38分 | |
【换取逻辑分析仪】-基于ADI单片机MAX78000的简易MP3音乐播放器被打赏48分 | |
我想要一部加热台+树莓派PICO驱动AHT10被打赏38分 | |
【换取逻辑分析仪】-硬件SPI驱动OLED屏幕被打赏36分 | |
换逻辑分析仪+上下拉与多路选择器被打赏29分 | |
Let'sdo第3期任务合集被打赏50分 | |
换逻辑分析仪+Verilog三态门被打赏27分 | |
换逻辑分析仪+Verilog多输出门被打赏24分 |