这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » DIY与开源设计 » 电子DIY » 关于PCF8563 的一些问题

共11条 1/2 1 2 跳转至

关于PCF8563 的一些问题

助工
2014-09-12 22:18:00     打赏

最近把PCF8563的日历驱动写好了,但是遇到些问题,特来请教各位大神,先把自己的代码贴上来:


`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: Charles Wang 
// 
// Create Date:    09/04//2014 
// Design Name: 	PCF8563_Calendar
// Module Name:   PCF8563_Cal
// Project Name: 	PCF8563_Calendar
// Target Devices: EP4CE6E22C8
// Tool versions: Quartus II 13.1 
// Description: 使用LED 数码管显示PCF8563中的日历(年、月、日) --顶层模块
//              
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//			
//////////////////////////////////////////////////////////////////////////////////
module PCF8563_Cal(sys_clk,sys_rst_n,sda,scl,disp_seg,cs);

input sys_clk;//总线时钟,50MHz
input sys_rst_n;//异步复位,低电平有效

inout sda;//SDA 总线
output scl;//SCL 总线
output [7:0]disp_seg;//数码管段选
output [7:0]cs;//数码管位选

wire [7:0] year;//年数据
wire [7:0] month;//月数据
wire [7:0] day;//日数据
//////////////////////////////////////////////////////////////////////////////////
//例化I2C模块
PCF8563_I2C I2C(.sys_clk(sys_clk),.sys_rst_n(sys_rst_n),.sda(sda),
.scl(scl),.year(year),.month(month),.day(day));
 //////////////////////////////////////////////////////////////////////////////////
 //例化LED数码管显示模块
PCF8563_LED LED(.sys_clk(sys_clk),.sys_rst_n(sys_rst_n),.disp_seg
(disp_seg),.cs(cs),.year(year),.month(month),.day(day));
endmodule 

 

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: Charles Wang 
// 
// Create Date:    09/04//2014 
// Design Name: 	PCF8563_Calendar
// Module Name:   PCF8563_I2C
// Project Name: 	PCF8563_Calendar
// Target Devices: EP4CE6E22C8
// Tool versions: Quartus II 13.1 
// Description: 使用LED 数码管显示PCF8563中的日历(年、月、日) --I2C 总线模块
//              
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//			
//////////////////////////////////////////////////////////////////////////////////
module PCF8563_I2C(sys_rst_n,sys_clk,scl,sda,year,month,day);
input sys_clk;//总线时钟,50MHz
input sys_rst_n;//异步复位,低电平有效

output scl;//SCL 总线
inout  sda;//SDA 总线
output [7:0]year;//日历,年,数据
output [7:0]month;//日历,月,数据
output [7:0]day;//日历,日,数据

reg scl;//SCL 信号寄存器
reg sda_r;//SDA 信号寄存器
reg sda_link;//SDA 方向标志寄存器
reg [7:0]year_r;//年数据寄存器
reg [7:0]month_r;//月数据寄存器
reg [7:0]week_r;//周数据寄存器,读出来之后不显示
reg [7:0]day_r;//日数据寄存器
reg [7:0]slave_addr;//从机地址寄存器
reg [7:0]reg_addr;//数据地址寄存器
reg [4:0]state;//状态寄存器
reg [3:0]data_cnt;//数据计数器
reg [7:0]scl_cnt;//产生SCL 信号计数器
reg [2:0]cnt;
//////////////////////////////////////////////////////////////////////////////////
//进程1、2、3: 产生 SCL 总线时钟
always@(posedge sys_clk or negedge sys_rst_n)
	begin
		if(!sys_rst_n)
			scl_cnt <= 8'd0;
		else if(scl_cnt == 8'd199)
			scl_cnt <= 8'd0;
		else
			scl_cnt <= scl_cnt + 1'b1;
	end
always@(posedge sys_clk or negedge sys_rst_n)
	begin
		if(!sys_rst_n)
			cnt <= 3'd5;
		else 
			case(scl_cnt)
				8'd49: cnt <= 3'd1;//高电平中间
				8'd99: cnt <= 3'd2;//下降沿
				8'd149:cnt <= 3'd3;//低电平中间
				8'd199:cnt <= 3'd0;//上升沿
			   default: cnt <= 3'd5;
			endcase
	end
`define SCL_HIG (cnt == 3'd1)
`define SCL_NEG (cnt == 3'd2)
`define SCL_LOW (cnt == 3'd3)
`define SCL_POS (cnt == 3'd0)
always@(posedge sys_clk or negedge sys_rst_n)
	begin
		if(!sys_rst_n)
			scl <= 1'b0;
		else if(`SCL_POS)
			scl <= 1'b1;
		else if(`SCL_NEG)
			scl <= 1'b0;
	end
 //////////////////////////////////////////////////////////////////////////////////
 //状态机定义
 parameter          IDLE                 = 5'd1,//空闲
			  START1 	         = 5'd2,//产生起始信号
			  SLAVE_ADDR1   = 5'd3,//写从机地址
			  ACK1                = 5'd4,//从机应答
			  DAY_ADDR	  = 5'd5,//写日数据地址
			  ACK2		  = 5'd6,//从机应答
			  RE_START1   = 5'd7,//再次产生起始信号
			  SLAVE_ADDR2 = 5'd8,//读从机地址
			  ACK3        = 5'd9,//从机应答
			  DAY_DATA	  = 5'd10,//读日数据
			  ACK4		  = 5'd11,//主机应答
			  WK_DATA	  = 5'd12,//读周数据
			  ACK5        = 5'D13,//主机应答
			  MONTH_DATA  = 5'd14,//读月数据
			  ACK6	     = 5'd15,//主机应答
			  YEAR_DATA   = 5'd16,//读年数据
			  NACK        = 5'd17,//主机非应答
			  STOP        = 5'd18;//产生停止信号
parameter  SLAVE_AD_W  = 8'ha2,//从机地址,写
			  SLAVE_AD_R  = 8'ha3,//从机地址,读
			  YEAR_AD     = 8'h08,//年数据地址
			  MONTH_AD    = 8'h07,//月数据地址
			  DAY_AD      = 8'h05;//日数据地址
 //////////////////////////////////////////////////////////////////////////////////
 //进程4:状态转换
always@(posedge sys_clk or negedge sys_rst_n)
	begin
		if(!sys_rst_n)
			begin
				state 		<= IDLE;
				year_r		<= 8'hff;
				month_r		<= 8'hff;
				day_r 		<= 8'hff;
				week_r		<= 8'hff;
				slave_addr	<= 8'h0;
				reg_addr		<= 8'h0;
				sda_r			<= 1'b1;
				sda_link 	<= 1'b1;
				data_cnt		<= 4'd0;
			end
		else
			case(state)
				IDLE:
					begin
						sda_r 	<= 1'b1;
						sda_link	<= 1'b1;
					end
				START1:
					begin
						if(`SCL_HIG)
							begin
								sda_r			<= 1'b0;
								sda_link		<= 1'b1;
								state			<= SLAVE_ADDR1;
								slave_addr 	<= SLAVE_AD_W;
								reg_addr		<= DAY_AD;
							end
						else
							state <= START1;
					end
				SLAVE_ADDR1:
					begin
						if(`SCL_LOW)
							begin
								if(data_cnt == 4'd8)
									begin
										data_cnt <= 4'd0;
										state		<= ACK1;
										sda_r		<= 1'b1;
										sda_link	<= 1'b0;
									end
								else
									begin
										data_cnt <= data_cnt + 1'b1;
										state		<= SLAVE_ADDR1;
										case(data_cnt)
											4'd0: sda_r <= slave_addr[7];
											4'd1: sda_r <= slave_addr[6];
											4'd2: sda_r <= slave_addr[5];
											4'd3: sda_r <= slave_addr[4];
											4'd4: sda_r <= slave_addr[3];
											4'd5: sda_r <= slave_addr[2];
											4'd6: sda_r <= slave_addr[1];
											4'd7: sda_r <= slave_addr[0];
											default: ;
										endcase
									end
							end
						else
							state <= SLAVE_ADDR1;
					end
				ACK1:
					begin
						if(`SCL_HIG && (!sda))
							begin
								state 	<= DAY_ADDR;
								reg_addr <= DAY_AD;
							end
						else if(`SCL_NEG)
							begin
								state 	<= DAY_ADDR;
								reg_addr <= DAY_AD;
							end
						else
							state <= ACK1;
					end
				DAY_ADDR:
					begin
						if(`SCL_LOW)
							begin
								if(data_cnt == 4'd8)
									begin
										data_cnt <= 4'd0;
										state		<= ACK2;
										sda_r		<= 1'b1;
										sda_link	<= 1'b0;
									end
								else
									begin
										data_cnt <= data_cnt + 1'b1;
										state		<= DAY_ADDR;
										case(data_cnt)
											4'd0: sda_r <= reg_addr[7];
											4'd1: sda_r <= reg_addr[6];
											4'd2: sda_r <= reg_addr[5];
											4'd3: sda_r <= reg_addr[4];
											4'd4: sda_r <= reg_addr[3];
											4'd5: sda_r <= reg_addr[2];
											4'd6: sda_r <= reg_addr[1];
											4'd7: sda_r <= reg_addr[0];
											default: ;
										endcase
									end
							end
					end
				ACK2:
					begin
						if(`SCL_HIG &&(!sda))
							begin
								state 	<= RE_START1;
								sda_r		<= 1'b1;
								sda_link <= 1'b1;
							end
						else if(`SCL_NEG)
							begin
								state		<= RE_START1;
								sda_r		<= 1'b1;
								sda_link <= 1'b1;
							end
						else
							state <= ACK2;
					end
				RE_START1:
					begin
						if(`SCL_HIG)
							begin
								sda_r			<= 1'b0;
								sda_link		<= 1'b1;
								state			<= SLAVE_ADDR2;
								slave_addr 	<= SLAVE_AD_R;
							end
						else
							state	<= RE_START1;
					end
				SLAVE_ADDR2:
					begin
						if(`SCL_LOW)
							begin
								if(data_cnt == 4'd8)
									begin
										data_cnt <= 4'd0;
										state		<= ACK3;
										sda_r		<= 1'b1;
										sda_link	<= 1'b0;
									end
								else
									begin
										data_cnt <= data_cnt + 1'b1;
										state		<= SLAVE_ADDR2;
										case(data_cnt)
											4'd0: sda_r <= slave_addr[7];
											4'd1: sda_r <= slave_addr[6];
											4'd2: sda_r <= slave_addr[5];
											4'd3: sda_r <= slave_addr[4];
											4'd4: sda_r <= slave_addr[3];
											4'd5: sda_r <= slave_addr[2];
											4'd6: sda_r <= slave_addr[1];
											4'd7: sda_r <= slave_addr[0];
											default: ;
										endcase
									end
							end
						else
							state <= SLAVE_ADDR2;
					end
				ACK3:
					begin
						if(`SCL_HIG &&(!sda))
							begin
								state 	<= DAY_DATA;
							end
						else if(`SCL_NEG)
							begin
								state		<= DAY_DATA;

							end
						else
							state <= ACK3;
					end
				DAY_DATA:
					begin
						if(`SCL_LOW && (data_cnt == 4'd8))
							begin
								data_cnt <= 4'd0;
								state 	<= ACK4;
								sda_r 	<= 1'b1;
								sda_link <= 1'b0;
							end
						else if(`SCL_HIG)
							begin
								state 	<= DAY_DATA;
								data_cnt <= data_cnt + 1'b1;
								case(data_cnt)
									4'd0: day_r[7] <= sda;
									4'd1: day_r[6] <= sda;
									4'd2: day_r[5] <= sda;
									4'd3: day_r[4] <= sda;
									4'd4: day_r[3] <= sda;
									4'd5: day_r[2] <= sda;
									4'd6: day_r[1] <= sda;
									4'd7: day_r[0] <= sda;
									default: ;
								endcase
							end
					end
				ACK4:
					begin
						if(`SCL_LOW)
							begin
								sda_r 	<= 1'b0;
								state		<= WK_DATA;
							end
						else if(`SCL_NEG)
							begin
								sda_r		<= 1'b1;
								state		<= WK_DATA;
							end
						else
							state <= ACK4;
					end
				WK_DATA:
					begin
						if(`SCL_LOW && (data_cnt == 4'd8))
							begin
								data_cnt <= 4'd0;
								state 	<= ACK5;
								sda_r 	<= 1'b1;
								sda_link <= 1'b0;
							end
						else if(`SCL_HIG)
							begin
								state 	<= WK_DATA;
								data_cnt <= data_cnt + 1'b1;
								case(data_cnt)
									4'd0: week_r[7] <= sda;
									4'd1: week_r[6] <= sda;
									4'd2: week_r[5] <= sda;
									4'd3: week_r[4] <= sda;
									4'd4: week_r[3] <= sda;
									4'd5: week_r[2] <= sda;
									4'd6: week_r[1] <= sda;
									4'd7: week_r[0] <= sda;
									default: ;
								endcase
							end
					end
				ACK5:
					begin
						if(`SCL_LOW)
							begin
								sda_r 	<= 1'b0;
								state		<= MONTH_DATA;
							end
						else if(`SCL_NEG)
							begin
								sda_r		<= 1'b1;
								state		<= MONTH_DATA;
							end
						else
							state <= ACK5;
					end
				MONTH_DATA:
					begin
						if(`SCL_LOW && (data_cnt == 4'd8))
							begin
								data_cnt <= 4'd0;
								state 	<= ACK6;
								sda_r 	<= 1'b1;
								sda_link <= 1'b0;
							end
						else if(`SCL_HIG)
							begin
								state 	<= MONTH_DATA;
								data_cnt <= data_cnt + 1'b1;
								case(data_cnt)
									4'd0: month_r[7] <= sda;
									4'd1: month_r[6] <= sda;
									4'd2: month_r[5] <= sda;
									4'd3: month_r[4] <= sda;
									4'd4: month_r[3] <= sda;
									4'd5: month_r[2] <= sda;
									4'd6: month_r[1] <= sda;
									4'd7: month_r[0] <= sda;
									default: ;
								endcase
							end
					end
				ACK6:
					begin
						if(`SCL_LOW)
							begin
								sda_r 	<= 1'b0;
								state		<= YEAR_DATA;
							end
						else if(`SCL_NEG)
							begin
								sda_r		<= 1'b1;
								state		<= YEAR_DATA;
							end
						else
							state <= ACK6;
					end
				YEAR_DATA:
					begin
						if(`SCL_LOW && (data_cnt == 4'd8))
							begin
								data_cnt <= 4'd0;
								state 	<= NACK;
								sda_r 	<= 1'b1;
								sda_link <= 1'b0;
							end
						else if(`SCL_HIG)
							begin
								state 	<= YEAR_DATA;
								data_cnt <= data_cnt + 1'b1;
								case(data_cnt)
									4'd0: year_r[7] <= sda;
									4'd1: year_r[6] <= sda;
									4'd2: year_r[5] <= sda;
									4'd3: year_r[4] <= sda;
									4'd4: year_r[3] <= sda;
									4'd5: year_r[2] <= sda;
									4'd6: year_r[1] <= sda;
									4'd7: year_r[0] <= sda;
									default: ;
								endcase
							end
					end
				NACK:
					begin
						if(`SCL_LOW)
							begin
								state <= STOP;
								sda_r	<= 1'b0;
							end
							else
								state <= NACK;
					end
				STOP:
					begin
						if(`SCL_HIG)
							begin
								state <= IDLE;
								sda_r <= 1'b1;
							end
						else
							state <= STOP;
					end
				default: state	<= IDLE;
			endcase
	end
assign year  = year_r;
assign month = month_r;
assign day	 = day_r;
assign sda = sda_link ? sda_r:1'bz;
endmodule
 
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: Charles Wang 
// 
// Create Date:    09/04//2014 
// Design Name: 	PCF8563_Calendar
// Module Name:   PCF8563_LED
// Project Name: 	PCF8563_Calendar
// Target Devices: EP4CE6E22C8
// Tool versions: Quartus II 13.1 
// Description: 使用LED 数码管显示PCF8563中的日历(年、月、日) --LED显示模块
//              
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//			
//////////////////////////////////////////////////////////////////////////////////
module PCF8563_LED(sys_clk,sys_rst_n,year,month,day,disp_seg,cs);
input sys_clk;//总线时钟,50MHz
input sys_rst_n;//异步复位,低电平复位
input [7:0]year;//年数据
input [7:0]month;//月数据
input [7:0]day;//日数据

output[7:0]disp_seg;//数码管段选
output[7:0]cs;//数码管位选

reg [12:0]cs_cnt;//位选扫描时钟计数器
reg [2:0]cs_clk;//位选时钟
reg [7:0]cs;//位选寄存器
reg [7:0]disp_seg;//数码管段选寄存器
reg [3:0]data_buff;//日历数据寄存器
///////////////////////////////////////////////////////////////////////////////////
//进程1、2、3:产生位选扫描时钟
always@(posedge sys_clk or negedge sys_rst_n)
	begin
		if(!sys_rst_n)
			begin
				cs_cnt <= 13'd0;
			end
		else if(cs_cnt == 13'd4999)
			begin
				cs_cnt <= 13'd0;
			end
		else
			begin
				cs_cnt <= cs_cnt + 1'b1;
			end
	end
always@(posedge sys_clk or negedge sys_rst_n)
	begin
		if(!sys_rst_n)
			begin
				cs_clk <= 3'd0;
			end
		else if(cs_cnt == 13'd4999)
			begin
				cs_clk <= cs_clk + 1'b1;
			end
	end
always@(posedge sys_clk or negedge sys_rst_n)
	begin
		if(!sys_rst_n)
			begin
				cs <= 8'hff;
			end
		else
			case(cs_clk)
				3'd0: cs <= 8'b1111_1110;
				3'd1: cs <= 8'b1111_1101;
				3'd2: cs <= 8'b1111_1011;
				3'd3: cs <= 8'b1111_0111;
				3'd4: cs <= 8'b1110_1111;
				3'd5: cs <= 8'b1101_1111;
				3'd6: cs <= 8'b1011_1111;
				3'd7: cs <= 8'b0111_1111;
				default: cs <= 8'b1111_1111;
			endcase
	end
 //////////////////////////////////////////////////////////////////////////////////
 //进程3、4:LED 数码管显示
always@(posedge sys_clk or negedge sys_rst_n)
	begin
		if(!sys_rst_n)
			begin
				data_buff <= 4'hf;
			end
		else
			case(cs)
				8'b1111_1110: data_buff <= {day[3:0]};
				8'b1111_1101: data_buff <= {2'd0,day[5:4]};
				8'b1111_1011: data_buff <= {month[3:0]};
				8'b1111_0111: data_buff <= {3'd0,month[4]};
				8'b1110_1111: data_buff <= {year[3:0]};
				8'b1101_1111: data_buff <= {year[7:4]};
				8'b1011_1111: data_buff <=  4'hf;
				8'b0111_1111: data_buff <=  4'hf;
				default		: data_buff	<=  4'hf;
			endcase
	end
always@(posedge sys_clk or negedge sys_rst_n)
	begin
		if(!sys_rst_n)
			begin
				disp_seg <= 8'hff;
			end
		else 	
			case(data_buff)
				4'h0 : disp_seg <= 8'hc0;   // "0"
				4'h1 : disp_seg <= 8'hf9;   // "1"
				4'h2 : disp_seg <= 8'ha4;   // "2"
				4'h3 : disp_seg <= 8'hb0;   // "3"
				4'h4 : disp_seg <= 8'h99;   // "4"
				4'h5 : disp_seg <= 8'h92;   // "5"
				4'h6 : disp_seg <= 8'h82;   // "6"
				4'h7 : disp_seg <= 8'hf8;   // "7"
				4'h8 : disp_seg <= 8'h80;   // "8"
				4'h9 : disp_seg <= 8'h90;   // "9"
				4'ha : disp_seg <= 8'h88;	 // "a"
				4'hb : disp_seg <= 8'h83;   // "b"
				4'hc : disp_seg <= 8'hc6;   // "c"
				4'hd : disp_seg <= 8'ha1;   // "d"
				4'he : disp_seg <= 8'h86;   // "e"
				4'hf : disp_seg <= 8'h8e;   // "f"
				default: disp_seg <= 8'hff;
			endcase
	end
endmodule

 


 




关键词: 关于     PCF8563     一些     问题    

助工
2014-09-12 22:22:09     打赏
2楼

现象如下:


助工
2014-09-12 22:33:35     打赏
3楼

这里遇到了问题,就是:

    1. 读出来的日历数据,是不对的,但又不知道为什么,我是按照Master reads after setting word address ,这个mode 来读数据的

    2. 有没有一个方法,在读完day 数据之后,跳过Week ,直接读month 数据,year 数据 呢?

    

    谢谢各位指点,


助工
2014-09-13 23:07:51     打赏
4楼

修改了I2C 模块及LED 显示模块的代码如下:

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: Charles Wang 
// 
// Create Date:    09/04//2014 
// Design Name: 	PCF8563_Calendar
// Module Name:   PCF8563_I2C
// Project Name: 	PCF8563_Calendar
// Target Devices: EP4CE6E22C8
// Tool versions: Quartus II 13.1 
// Description: 使用LED 数码管显示PCF8563中的日历数据(年、月、日) --I2C 总线模块
//              
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//			
//////////////////////////////////////////////////////////////////////////////////
module PCF8563_I2C(sys_rst_n,sys_clk,scl,sda,year,month,day);
input sys_clk;//总线时钟,50MHz
input sys_rst_n;//异步复位,低电平有效

output scl;//SCL 总线
inout  sda;//SDA 总线
output [7:0]year;//日历,年,数据
output [7:0]month;//日历,月,数据
output [7:0]day;//日历,日,数据

reg scl;//SCL 信号寄存器
reg sda_r;//SDA 信号寄存器
reg sda_link;//SDA 方向标志寄存器
reg [7:0]year_r;//年数据寄存器
reg [7:0]month_r;//月数据寄存器
reg [7:0]week_r;//周数据寄存器,读出来之后不显示
reg [7:0]day_r;//日数据寄存器
reg [7:0]slave_addr;//从机地址寄存器
reg [7:0]reg_addr;//数据地址寄存器
reg [4:0]state;//状态寄存器
reg [3:0]data_cnt;//数据计数器
reg [7:0]scl_cnt;//产生SCL 信号计数器
reg [2:0]cnt;
//////////////////////////////////////////////////////////////////////////////////
//进程1、2、3: 产生 SCL 总线时钟
always@(posedge sys_clk or negedge sys_rst_n)
	begin
		if(!sys_rst_n)
			scl_cnt <= 8'd0;
		else if(scl_cnt == 8'd199)
			scl_cnt <= 8'd0;
		else
			scl_cnt <= scl_cnt + 1'b1;
	end
always@(posedge sys_clk or negedge sys_rst_n)
	begin
		if(!sys_rst_n)
			cnt <= 3'd5;
		else 
			case(scl_cnt)
				8'd49: cnt <= 3'd1;//高电平中间
				8'd99: cnt <= 3'd2;//下降沿
				8'd149:cnt <= 3'd3;//低电平中间
				8'd199:cnt <= 3'd0;//上升沿
			   default: cnt <= 3'd5;
			endcase
	end
`define SCL_HIG (cnt == 3'd1)
`define SCL_NEG (cnt == 3'd2)
`define SCL_LOW (cnt == 3'd3)
`define SCL_POS (cnt == 3'd0)
always@(posedge sys_clk or negedge sys_rst_n)
	begin
		if(!sys_rst_n)
			scl <= 1'b0;
		else if(`SCL_POS)
			scl <= 1'b1;
		else if(`SCL_NEG)
			scl <= 1'b0;
	end
 //////////////////////////////////////////////////////////////////////////////////
 //状态机定义
 parameter IDLE  		  = 5'd1,//空闲
			  START1 	  = 5'd2,//产生起始信号
			  SLAVE_ADDR1 = 5'd3,//从机地址,写
			  ACK1        = 5'd4,//从机应答
			  DAY_ADDR	  = 5'd5,//数据地址,日,写
			  ACK2		  = 5'd6,//从机应答
			  RE_START1   = 5'd7,//再次产生起始信号
			  SLAVE_ADDR2 = 5'd8,//从机地址,读
			  ACK3        = 5'd9,//从机应答
			  DAY_DATA	  = 5'd10,//读数据,日
			  ACK4		  = 5'd11,//主机应答
			  WK_DATA	  = 5'd12,//读数据,周
			  ACK5        = 5'd13,//主机应答
			  MONTH_DATA  = 5'd14,//读数据,月
			  ACK6	     = 5'd15,//主机应答
			  YEAR_DATA   = 5'd16,//读数据,年
			  NACK        = 5'd17,//主机非应答
			  STOP        = 5'd18;//产生停止信号
parameter  SLAVE_AD_W  = 8'ha2,//从机地址,写
			  SLAVE_AD_R  = 8'ha3,//从机地址,读
			  YEAR_AD     = 8'h08,//年数据地址
			  MONTH_AD    = 8'h07,//月数据地址
			  DAY_AD      = 8'h05;//日数据地址
 //////////////////////////////////////////////////////////////////////////////////
 //进程4:状态转换
always@(posedge sys_clk or negedge sys_rst_n)
	begin
		if(!sys_rst_n)
			begin
				state 		<= IDLE;
				year_r		<= 8'h0;
				month_r		<= 8'h0;
				day_r 		<= 8'h0;
				week_r		<= 8'h0;
				slave_addr	<= 8'h0;
				reg_addr		<= 8'h0;
				sda_r			<= 1'b1;
				sda_link 	<= 1'b1;
				data_cnt		<= 4'd0;
			end
		else
			case(state)
				IDLE:
					begin
						sda_r 	<= 1'b1;
						sda_link	<= 1'b1;
					end
				START1:
					begin
						if(`SCL_HIG)
							begin
								sda_r			<= 1'b0;
								sda_link		<= 1'b1;
								state			<= SLAVE_ADDR1;
								slave_addr 	<= SLAVE_AD_W;
								reg_addr		<= DAY_AD;
							end
						else
							state <= START1;
					end
				SLAVE_ADDR1:
					begin
						if(`SCL_LOW)
							begin
								if(data_cnt == 4'd8)
									begin
										data_cnt <= 4'd0;
										state		<= ACK1;
										sda_r		<= 1'b1;
										sda_link	<= 1'b0;
									end
								else
									begin
										data_cnt <= data_cnt + 1'b1;
										state		<= SLAVE_ADDR1;
										case(data_cnt)
											4'd0: sda_r <= slave_addr[7];
											4'd1: sda_r <= slave_addr[6];
											4'd2: sda_r <= slave_addr[5];
											4'd3: sda_r <= slave_addr[4];
											4'd4: sda_r <= slave_addr[3];
											4'd5: sda_r <= slave_addr[2];
											4'd6: sda_r <= slave_addr[1];
											4'd7: sda_r <= slave_addr[0];
											default: ;
										endcase
									end
							end
						else
							state <= SLAVE_ADDR1;
					end
				ACK1:
					begin
						if((`SCL_HIG) && (!sda))
							begin
								state 	<= DAY_ADDR;
								reg_addr <= DAY_AD;
								sda_r		<= 1'b1;
								sda_link <= 1'b1;
							end
						else if(`SCL_NEG)
							begin
								state 	<= DAY_ADDR;
								reg_addr <= DAY_AD;
								sda_r		<= 1'b1;
								sda_link <= 1'b1;
							end
						else
							state <= ACK1;
					end
				DAY_ADDR:
					begin
						if(`SCL_LOW)
							begin
								if(data_cnt == 4'd8)
									begin
										data_cnt <= 4'd0;
										state		<= ACK2;
										sda_r		<= 1'b1;
										sda_link	<= 1'b0;
									end
								else
									begin
										data_cnt <= data_cnt + 1'b1;
										state		<= DAY_ADDR;
										case(data_cnt)
											4'd0: sda_r <= reg_addr[7];
											4'd1: sda_r <= reg_addr[6];
											4'd2: sda_r <= reg_addr[5];
											4'd3: sda_r <= reg_addr[4];
											4'd4: sda_r <= reg_addr[3];
											4'd5: sda_r <= reg_addr[2];
											4'd6: sda_r <= reg_addr[1];
											4'd7: sda_r <= reg_addr[0];
											default: ;
										endcase
									end
							end
						else
							state <= DAY_ADDR;
					end
				ACK2:
					begin
						if((`SCL_HIG) &&(!sda))
							begin
								state 	<= RE_START1;
								sda_r		<= 1'b1;
								sda_link <= 1'b1;
							end
						else if(`SCL_NEG)
							begin
								state		<= RE_START1;
								sda_r		<= 1'b1;
								sda_link <= 1'b1;
							end
						else
							state <= ACK2;
					end
				RE_START1:
					begin
						if(`SCL_HIG)
							begin
								sda_r			<= 1'b0;
								sda_link		<= 1'b1;
								state			<= SLAVE_ADDR2;
								slave_addr 	<= SLAVE_AD_R;
							end
						else
							state	<= RE_START1;
					end
				SLAVE_ADDR2:
					begin
						if(`SCL_LOW)
							begin
								if(data_cnt == 4'd8)
									begin
										data_cnt <= 4'd0;
										state		<= ACK3;
										sda_r		<= 1'b1;
										sda_link	<= 1'b0;
									end
								else
									begin
										data_cnt <= data_cnt + 1'b1;
										state		<= SLAVE_ADDR2;
										case(data_cnt)
											4'd0: sda_r <= slave_addr[7];
											4'd1: sda_r <= slave_addr[6];
											4'd2: sda_r <= slave_addr[5];
											4'd3: sda_r <= slave_addr[4];
											4'd4: sda_r <= slave_addr[3];
											4'd5: sda_r <= slave_addr[2];
											4'd6: sda_r <= slave_addr[1];
											4'd7: sda_r <= slave_addr[0];
											default: ;
										endcase
									end
							end
						else
							state <= SLAVE_ADDR2;
					end
				ACK3:
					begin
						if((`SCL_HIG) &&(!sda))
							begin
								state 	<= DAY_DATA;
							end
						else if(`SCL_NEG)
							begin
								state		<= DAY_DATA;
							end
						else
							state <= ACK3;
					end
				DAY_DATA:
					begin
						if((`SCL_LOW) && (data_cnt == 4'd8))
							begin
								data_cnt <= 4'd0;
								state 	<= ACK4;
								sda_r 	<= 1'b1;
								sda_link <= 1'b0;
							end
						else if(`SCL_HIG)
							begin
								state 	<= DAY_DATA;
								data_cnt <= data_cnt + 1'b1;
								case(data_cnt)
									4'd0: day_r[7] <= sda;
									4'd1: day_r[6] <= sda;
									4'd2: day_r[5] <= sda;
									4'd3: day_r[4] <= sda;
									4'd4: day_r[3] <= sda;
									4'd5: day_r[2] <= sda;
									4'd6: day_r[1] <= sda;
									4'd7: day_r[0] <= sda;
									default: ;
								endcase
							end
						else
							state <= DAY_DATA;
					end
				ACK4:
					begin
						if(`SCL_LOW)
							begin
								sda_r 	<= 1'b0;
								state		<= WK_DATA;
							end
						else if(`SCL_NEG)
							begin
								sda_r		<= 1'b1;
								state		<= WK_DATA;
							end
						else
							state <= ACK4;
					end
				WK_DATA:
					begin
						if((`SCL_LOW) && (data_cnt == 4'd8))
							begin
								data_cnt <= 4'd0;
								state 	<= ACK5;
								sda_r 	<= 1'b1;
								sda_link <= 1'b0;
							end
						else if(`SCL_HIG)
							begin
								state 	<= WK_DATA;
								data_cnt <= data_cnt + 1'b1;
								case(data_cnt)
									4'd0: week_r[7] <= sda;
									4'd1: week_r[6] <= sda;
									4'd2: week_r[5] <= sda;
									4'd3: week_r[4] <= sda;
									4'd4: week_r[3] <= sda;
									4'd5: week_r[2] <= sda;
									4'd6: week_r[1] <= sda;
									4'd7: week_r[0] <= sda;
									default: ;
								endcase
							end
						else 
							state <= WK_DATA;
					end
				ACK5:
					begin
						if(`SCL_LOW)
							begin
								sda_r 	<= 1'b0;
								state		<= MONTH_DATA;
							end
						else if(`SCL_NEG)
							begin
								sda_r		<= 1'b1;
								state		<= MONTH_DATA;
							end
						else
							state <= ACK5;
					end
				MONTH_DATA:
					begin
						if((`SCL_LOW) && (data_cnt == 4'd8))
							begin
								data_cnt <= 4'd0;
								state 	<= ACK6;
								sda_r 	<= 1'b1;
								sda_link <= 1'b0;
							end
						else if(`SCL_HIG)
							begin
								state 	<= MONTH_DATA;
								data_cnt <= data_cnt + 1'b1;
								case(data_cnt)
									4'd0: month_r[7] <= sda;
									4'd1: month_r[6] <= sda;
									4'd2: month_r[5] <= sda;
									4'd3: month_r[4] <= sda;
									4'd4: month_r[3] <= sda;
									4'd5: month_r[2] <= sda;
									4'd6: month_r[1] <= sda;
									4'd7: month_r[0] <= sda;
									default: ;
								endcase
							end
						else
							state <= MONTH_DATA;
					end
				ACK6:
					begin
						if(`SCL_LOW)
							begin
								sda_r 	<= 1'b0;
								state		<= YEAR_DATA;
							end
						else if(`SCL_NEG)
							begin
								sda_r		<= 1'b1;
								state		<= YEAR_DATA;
							end
						else
							state <= ACK6;
					end
				YEAR_DATA:
					begin
						if(`SCL_LOW && (data_cnt == 4'd8))
							begin
								data_cnt <= 4'd0;
								state 	<= NACK;
								sda_r 	<= 1'b1;
								sda_link <= 1'b0;
							end
						else if(`SCL_HIG)
							begin
								state 	<= YEAR_DATA;
								data_cnt <= data_cnt + 1'b1;
								case(data_cnt)
									4'd0: year_r[7] <= sda;
									4'd1: year_r[6] <= sda;
									4'd2: year_r[5] <= sda;
									4'd3: year_r[4] <= sda;
									4'd4: year_r[3] <= sda;
									4'd5: year_r[2] <= sda;
									4'd6: year_r[1] <= sda;
									4'd7: year_r[0] <= sda;
									default: ;
								endcase
							end
						else
							state <= YEAR_DATA;
					end
				NACK:
					begin
						if(`SCL_LOW)
							begin
								state <= STOP;
								sda_r	<= 1'b0;
							end
						else
							state <= NACK;
					end
				STOP:
					begin
						if(`SCL_HIG)
							begin
								state <= IDLE;
								sda_r <= 1'b1;
							end
						else
							state <= STOP;
					end
				default: state	<= IDLE;
			endcase
	end
assign year  = year_r;
assign month = month_r;
assign day	 = day_r;
assign sda = sda_link ? sda_r:1'bz;
endmodule
 
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: Charles Wang 
// 
// Create Date:    09/04//2014 
// Design Name: 	PCF8563_Calendar
// Module Name:   PCF8563_LED
// Project Name: 	PCF8563_Calendar
// Target Devices: EP4CE6E22C8
// Tool versions: Quartus II 13.1 
// Description: 使用LED 数码管显示PCF8563中的日历数据(年、月、日) --LED显示模块
//              
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//			
//////////////////////////////////////////////////////////////////////////////////
module PCF8563_LED(sys_clk,sys_rst_n,year,month,day,disp_seg,cs);
input sys_clk;//总线时钟,50MHz
input sys_rst_n;//异步复位,低电平复位
input [7:0]year;//数据,年
input [7:0]month;//数据,月
input [7:0]day;//数据,日

output[7:0]disp_seg;//数码管段选
output[7:0]cs;//数码管位选

reg [12:0]cs_cnt;//位选扫描时钟计数器
reg [2:0]cs_clk;//位选时钟
reg [7:0]cs;//位选寄存器
reg [7:0]disp_seg;//数码管段选寄存器
reg [3:0]data_buff;//日历数据寄存器
///////////////////////////////////////////////////////////////////////////////////
//进程1、2、3:产生位选扫描时钟
always@(posedge sys_clk or negedge sys_rst_n)
	begin
		if(!sys_rst_n)
			begin
				cs_cnt <= 13'd0;
			end
		else if(cs_cnt == 13'd4999)
			begin
				cs_cnt <= 13'd0;
			end
		else
			begin
				cs_cnt <= cs_cnt + 1'b1;
			end
	end
always@(posedge sys_clk or negedge sys_rst_n)
	begin
		if(!sys_rst_n)
			begin
				cs_clk <= 3'd0;
			end
		else if(cs_cnt == 13'd4999)
			begin
				cs_clk <= cs_clk + 1'b1;
			end
	end
always@(posedge sys_clk or negedge sys_rst_n)
	begin
		if(!sys_rst_n)
			begin
				cs <= 8'hff;
			end
		else
			case(cs_clk)
				3'd0: cs <= 8'b1111_1110;
				3'd1: cs <= 8'b1111_1101;
				3'd2: cs <= 8'b1111_1011;
				3'd3: cs <= 8'b1111_0111;
				3'd4: cs <= 8'b1110_1111;
				3'd5: cs <= 8'b1101_1111;
				3'd6: cs <= 8'b1011_1111;
				3'd7: cs <= 8'b0111_1111;
				default: cs <= 8'b1111_1111;
			endcase
	end
 //////////////////////////////////////////////////////////////////////////////////
 //进程3、4:LED 数码管显示
always@(posedge sys_clk or negedge sys_rst_n)
	begin
		if(!sys_rst_n)
			begin
				data_buff <= 4'hf;
			end
		else
			case(cs)
				8'b1111_1110: data_buff <= {day[3:0]};
				8'b1111_1101: data_buff <= {2'd0,day[5:4]};
				8'b1111_1011: data_buff <= {month[3:0]};
				8'b1111_0111: data_buff <= {3'd0,month[4]};
				8'b1110_1111: data_buff <= {year[3:0]};
				8'b1101_1111: data_buff <= {year[7:4]};
				8'b1011_1111: data_buff <=  4'hf;
				8'b0111_1111: data_buff <=  4'hf;
				default		: data_buff	<=  4'hf;
			endcase
	end
always@(posedge sys_clk or negedge sys_rst_n)
	begin
		if(!sys_rst_n)
			begin
				disp_seg <= 8'hff;
			end
		else 	
			case(data_buff)
				4'h0 : disp_seg <= 8'hc0;   // "0"
				4'h1 : disp_seg <= 8'hf9;   // "1"
				4'h2 : disp_seg <= 8'ha4;   // "2"
				4'h3 : disp_seg <= 8'hb0;   // "3"
				4'h4 : disp_seg <= 8'h99;   // "4"
				4'h5 : disp_seg <= 8'h92;   // "5"
				4'h6 : disp_seg <= 8'h82;   // "6"
				4'h7 : disp_seg <= 8'hf8;   // "7"
				4'h8 : disp_seg <= 8'h80;   // "8"
				4'h9 : disp_seg <= 8'h90;   // "9"
				default: disp_seg <= 8'hff;
			endcase
	end
endmodule

 

现象如下,但是不知道是否是对的


 

以上仅供参考


助工
2014-09-13 23:08:38     打赏
5楼
图片挂了,重发

院士
2014-09-14 08:30:28     打赏
6楼
其实这种问题最好粘贴设计流程图。这么多的代码,要花多长时间去分析啊!

院士
2014-09-14 14:41:57     打赏
7楼
到点

助工
2014-09-14 21:00:00     打赏
8楼
说的也是哈,

助工
2014-09-14 21:00:46     打赏
9楼
这个。。。。。。Jack 老大说的是。

助工
2014-09-18 08:04:49     打赏
10楼
解决了没?我读出的也都是0。

共11条 1/2 1 2 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]