//.v
always @(posedge i_sys_clk or negedge i_rst_n) begin
if(!i_rst_n) begin
r_cpu_data <= 32'd0; end
else begin
r_cpu_data <= i_cpu_data; end
end
仿真信号直接在某个时间给 i_cpu_data赋值就行:#10 i_cpu_data = 32'h55aa55aa;
想法:程序中我是直接判断启动脉冲来了就去状态跳转、转换数据,所以仿真限号得设置i_cpu_data 的在启动脉冲前赋值。 觉得状态的切换可以再设置一点东西,判断一下这是的r_cpu_data 是不是被赋值了(可能数据i_cpu_data 还没来,r_cpu_data 还全是零)。 得看实际情况怎么用,收发应该沟通好了就没问题。
assign startpulse_align = i_startpulse &&(~startpulse_dl);
always @(posedge i_sys_clk or negedge i_rst_n) begin
if(!i_rst_n) begin
startpulse_dl <= 1'd0; end
else begin
startpulse_dl <= i_startpulse; end
end
波形示意如下:
(其中需要startpulse的持续时间不能太短,否则sys_clk还没检测到;)
always @(posedge i_sys_clk or negedge i_rst_n) begin
if(!i_rst_n) begin
//都初始化为0
end
else begin
if(phase_cnt == 10'd39) begin//这里判断是不是40个sys_clk过去了
phase_cnt <= 10'b0; end
else begin
phase_cnt <= phase_cnt + 10'b1;
end
if(phase_cnt == 10'd39) begin//这里判断phase0是不是可以到了,并在一个sys_clk后置会0;
phase0 <= 1'd1; end
else begin
phase0 <= 1'd0;
end
//另几个phase同理
end
end
if(phase0 == 1'b1) begin
o_scl_clk <= 1'b1; end
else if(phase2 == 1'b1) begin
o_scl_clk <= 1'b0; end
else o_scl_clk <= o_scl_clk;
ps:同样由于非阻塞赋值,所以后面仿真可以看到波形上SCL是变沿是phase脉冲的尾部;
IDLE:变量初始化;判断startpulse_align来没,来了去START;
START:判断 SCL为高 且 phase1为高 不,是的去TRANS;
TRANS:判断phase3为高不,为再判断数据个数够没有(一般收发双方会说好),够了去DELAY,不够继续接收;
r_data_cnt <= r_data_cnt + 10'b1;//非阻塞赋值,so这两行位置欧克
o_sda_data_com <= r_cpu_data[31 - r_data_cnt];
这里并行数据 r_cpu_data 一开始就保存下来了,这里把它一位位的输出成串行数据;
DELAY:延迟几个时钟单元(确保上个输出数据输出完整之类的),再把SDA线拉低(因为之后结束传输SDA需要由低到高);再去STOP;
o_sda_data_com <= 1'b0;
STOP:判断phase1为高不,为则把SDA拉高,并去IDLE;否则等phase1来;