module ds1302(
sys_clk,
sys_rstn,
ds1302_scl,
ds1302_data,
ds1302_ce,
hour,
minute,
second
);
input sys_clk;
input sys_rstn;
output ds1302_scl;
inout ds1302_data;
output ds1302_ce;
output [7:0]hour;
output [7:0]minute;
output [7:0]second;
/*
//产生时钟 200x20ns = 4us
reg [7:0]count;
always @(posedge sys_clk or negedge sys_rstn)
begin
if(!sys_rstn)
count <= 8'b0;
else if(count == 199)
count <= 8'b0;
else count <= count + 1'b1;
end
reg ds1302_scl_r;
always @(posedge sys_clk or negedge sys_rstn)
begin
if(!sys_rstn)
ds1302_scl_r <= 1'b0;
else if(count == 0)
ds1302_scl_r <= 1'b0;
else if(count == 99)
ds1302_scl_r <= 1'b1;
end
assign ds1302_scl = ds1302_scl_r;
`define POS_POINT (count == 99)
`define NEG_POINT (count == 199)
`define HIGH_POINT (count == 149)
`define LOW_POINT (count == 49)
*/
//200循环计数,产生iic所需要的时钟,250khz
reg [7:0]cnt_delay;
always @(posedge sys_clk or negedge sys_rstn)
begin
if(!sys_rstn)
cnt_delay <= 8'b0;
else if(cnt_delay==8'd199)
cnt_delay <= 8'b0;
else cnt_delay <= cnt_delay + 1'b1;
end
reg [2:0]cnt;
always @(posedge sys_clk or negedge sys_rstn)
begin
if(!sys_rstn)
cnt <= 3'd5;
else
case (cnt_delay)
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_POS (cnt==3'd0) //上升沿
`define SCL_HIG (cnt==3'd1) //高电平中间位置用于数据采样
`define SCL_NEG (cnt==3'd2) //下降沿
`define SCL_LOW (cnt==3'd3) //低电平中间位置用于数据变化
reg scl_r;
always @(posedge sys_clk or negedge sys_rstn)
begin
if(!sys_rstn)
scl_r <= 1'b1;
else if(`SCL_NEG) //下降沿
scl_r <= 1'b0;
else if(`SCL_POS) //上升沿
scl_r <= 1'b1;
end
assign ds1302_scl = scl_r;
`define SECOND_READ_ADDR 8'h81;
parameter START = 4'd1;
parameter WRITE_SECOND_ADDR = 4'd2;
parameter READ_SECOND_DATA = 4'd3;
parameter STOP = 4'd4;
reg [3:0]state;
reg [3:0]num;
reg [7:0]dr;
reg ds1302_ce_r;
reg ds1302_data_r;
reg ds1302_data_link; //方向选择
reg [7:0]second_rr;
reg [7:0]second_r;
always @(posedge sys_clk or negedge sys_rstn)
begin
if(!sys_rstn)
begin
state <= START;
num <= 4'd0;
dr <= 8'b0;
ds1302_ce_r <= 1'b0;
ds1302_data_r <= 1'b0;
ds1302_data_link <= 1'b1; //output
second_r <= 8'b0;
end
else
case (state)
START:
begin
num <= 4'd0;
ds1302_ce_r <= 1'b0;
ds1302_data_r <= 1'b0;
dr <= `SECOND_READ_ADDR;
ds1302_data_link <= 1'b1; //output
ds1302_ce_r <= 1'b1;
state <= WRITE_SECOND_ADDR;
end
WRITE_SECOND_ADDR:
begin
if(`SCL_NEG) //下降沿准备好数据准备好
begin
if(num==8)
begin
num <= 4'b0;
state <= READ_SECOND_DATA;
ds1302_data_link <= 1'b0; //input
end
else
begin
num <= num + 1'b1;
case (num)
4'd0: ds1302_data_r <= dr[0];
4'd1: ds1302_data_r <= dr[1];
4'd2: ds1302_data_r <= dr[2];
4'd3: ds1302_data_r <= dr[3];
4'd4: ds1302_data_r <= dr[4];
4'd5: ds1302_data_r <= dr[5];
4'd6: ds1302_data_r <= dr[6];
4'd7: ds1302_data_r <= dr[7];
default :;
endcase
state <= WRITE_SECOND_ADDR;
end
end
else state <= WRITE_SECOND_ADDR;
end
READ_SECOND_DATA:
begin
if(`SCL_NEG)
begin
if(num == 8)
begin
num <= 4'b0;
state <= STOP;
second_r <= second_rr;
ds1302_data_link <= 1'b1; //output
end
else
begin
num <= num + 1'b1;
case (num)
4'd0: second_rr[0] <= ds1302_data;
4'd1: second_rr[1] <= ds1302_data;
4'd2: second_rr[2] <= ds1302_data;
4'd3: second_rr[3] <= ds1302_data;
4'd4: second_rr[4] <= ds1302_data;
4'd5: second_rr[5] <= ds1302_data;
4'd6: second_rr[6] <= ds1302_data;
4'd7: second_rr[7] <= ds1302_data;
default :;
endcase
state <= READ_SECOND_DATA;
end
end
else state <= READ_SECOND_DATA;
end
STOP:
begin
ds1302_ce_r <= 1'b0;
state <= START;
end
default:state <= START;
endcase
end
assign ds1302_data = ds1302_data_link ? ds1302_data_r : 1'bz;
assign second = second_r;
assign ds1302_ce = ds1302_ce_r;
endmodule
一直找不到问题
有奖活动 | |
---|---|
【有奖活动——B站互动赢积分】活动开启啦! | |
【有奖活动】分享技术经验,兑换京东卡 | |
话不多说,快进群! | |
请大声喊出:我要开发板! | |
【有奖活动】EEPW网站征稿正在进行时,欢迎踊跃投稿啦 | |
奖!发布技术笔记,技术评测贴换取您心仪的礼品 | |
打赏了!打赏了!打赏了! |