赞
踩
源码地址:http://www.opencores.org/projects/i2c/
时序图在线绘制工具:https://wavedrom.com/
绘图工具:https://app.diagrams.net/
八位并行转串行
always @(posedge clk or negedge nReset)
begin
if (!nReset) // asynchronous reset
sr <= #1 8'h0; //the"#"just for modelsim,it's not used when Analysis & Synthesis
else if (rst==1) // synchronous reset
sr <= #1 8'h0;
else if (ld) // load data
sr <= #1 din; // write data to sda
else if (shift)
sr <= #1 {sr[6:0], core_rxd}; // read data from sda
end
八位计数器
always @(posedge clk or negedge nReset)
begin
if (!nReset)
dcnt <= #1 3'h0;
else if (rst)
dcnt <= #1 3'h0;
else if (ld)
dcnt <= #1 3'h7;
else if (shift)
dcnt <= #1 dcnt - 3'h1;
end
assign cnt_done = ~(|dcnt);
对串行后的每一位进行输出,每一位的输出可分成5个阶段(a、b、c、d、i),start多了一个e,其中i是idle
开始,读写,停止的时序如下:
start
stop
read
read里的SDA是高阻态,不是1,这样slave可以控制SDA,输出数据给master
write
SDA、SCL的数据并没有直接用,而是经历了很多filter
Capture
always @(posedge clk or negedge nReset) begin if (!nReset) begin cSCL <= #1 2'b00; cSDA <= #1 2'b00; end else if (rst) begin cSCL <= #1 2'b00; cSDA <= #1 2'b00; end else begin cSCL <= {cSCL[0],scl_i}; cSDA <= {cSDA[0],sda_i}; end end
Filter
always @(posedge clk or negedge nReset)//fSCL is the Operation control clock begin if(!nReset) begin fSCL <= 3'b111; fSDA <= 3'b111; end else if (rst) begin fSCL <= 3'b111; fSDA <= 3'b111; end else if (~|filter_cnt) begin fSCL <= {fSCL[1:0],cSCL[1]}; fSDA <= {fSDA[1:0],cSDA[1]}; end end
Synchronized、Delayed
always @(posedge clk or negedge nReset) begin if (~nReset) begin sSCL <= #1 1'b1; sSDA <= #1 1'b1; dSCL <= #1 1'b1; dSDA <= #1 1'b1; end else if (rst) begin sSCL <= #1 1'b1; sSDA <= #1 1'b1; dSCL <= #1 1'b1; dSDA <= #1 1'b1; end else begin sSCL <= #1 &fSCL[2:1] | &fSCL[1:0] | (fSCL[2] & fSCL[0]); sSDA <= #1 &fSDA[2:1] | &fSDA[1:0] | (fSDA[2] & fSDA[0]); dSCL <= #1 sSCL; dSDA <= #1 sSDA; end end // generate dout signal (store SDA on rising edge of SCL) always @(posedge clk) if(sSCL & ~dSCL) dout <= #1 sSDA;
仲裁失败(Aribitration lost)
//仲裁丢失:当检测到停止信号,没有检测到请求信号,主机设置SDA为高电平,但实际上SDA为低电平
always @(posedge clk or negedge nReset)
begin
if(~nReset)
al <= #1 1'b0;
else if(rst)
al <= #1 1'b0;
else
al <= #1 (sda_chk & ~sSDA & sda_oen)|(|c_state & sto_condition & ~cmd_stop);
end
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。