Verilog中的I2C从模块不承认

问题描述 投票:-1回答:2

我在Verilog中编写了这个I2C从模块:

module I2CSlave(
input iSCL,
input iI2C_CLK,
inout bSDA,
output reg [7:0] odata,
output reg oread,
output wire oactive
);    

reg incycle = 1'b0;
reg pSDA;
reg pSCL;
always @(posedge iI2C_CLK) begin
    if ((pSCL) && (iSCL) && (pSDA) && (~bSDA)) begin
        incycle <= 1;
    end
    if ((pSCL) && (iSCL) && (~pSDA) && (bSDA)) begin
        incycle <= 0;
    end
    pSDA <= bSDA;
    pSCL <= iSCL;
end

assign oactive = incycle;

localparam STATE_IDLE = 0;
localparam STATE_ADDR = 1;
localparam STATE_RW = 2;
localparam STATE_ACK = 3;
localparam STATE_DATA = 4;
localparam STATE_ACK2 = 5;

reg [7:0] i = 0;
reg [7:0] state = STATE_IDLE;
reg [6:0] addr = 7'h03;
reg addr_match = 1;
reg rw;

reg lSDA;
always @(posedge iSCL) lSDA <= bSDA;

assign bSDA = ((state == STATE_ACK) || (state == STATE_ACK2)) ? 0 : 1'bz;
assign oread = (state == STATE_ACK2);
assign ostate = i;

always @(negedge iSCL or negedge incycle) begin
    if (~incycle) begin
        state <= STATE_IDLE;
        addr_match <= 1;
    end
    else if (addr_match) begin
        case (state)
            STATE_IDLE: begin               
                state <= STATE_ADDR;
                i <= 7;
            end
            STATE_ADDR: begin
                if (addr[i-1] != lSDA) addr_match <= 0;
                if (i == 1) begin
                    state <= STATE_RW;
                    i <= i - 1;
                end
                else i <= i - 1;
            end
            STATE_RW: begin
                rw <= lSDA;
                state <= STATE_ACK;
            end
            STATE_ACK: begin
                state <= STATE_DATA;
                i = 7;
            end
            STATE_DATA : begin
                odata[i] <= lSDA;
                if (i == 0) state <= STATE_ACK2;
                else i <= i - 1;
            end
            STATE_ACK2: begin
                state <= STATE_DATA;
                i = 7;
            end
        endcase
    end
end

endmodule

截至目前,它应该只读取master发送的数据。它似乎在仿真中运行良好,但是当我将其上传到FPGA时,有时一切都还可以,但有时候它不会确认主机发送的数据,而它似乎忽略了它们。我是Verilog的新手,所以我希望,这不是一个愚蠢的问题。

verilog i2c
2个回答
0
投票

在真实硬件上运行时随机失败的一个可能原因是您没有同步输入。

您正在采样缓慢变化的信号(i2c总线将具有长斜率),这些信号与您的设计时钟完全不同步。根据您的运气,您的fpga d-flops的设置/保持时间会随机违规,从而导致亚稳态问题。寄存器中的相同值可能在芯片的多个部分中被区别对待。这将对你的i2c奴隶的逻辑造成严重破坏。

您必须同步异步输入,在最简单的情况下,将它传递给几个寄存器,然后再将其提供给模块的fsm。


0
投票

您的代码有几个问题,可能会导致模拟和综合行为不匹配。例如,以下内容不可综合,并且被综合工具忽略。所以,你的初始状态会有所不同。检查日志以获取警告。不要使用regs的声明作业。 (好的电线)。

reg [7:0] i = 0;
reg [7:0] state = STATE_IDLE;
reg [6:0] addr = 7'h03;
reg addr_match = 1;

以上意味着您初始化不起作用。

你搞砸了状态机中的阻塞和非阻塞分配。确保在'i = 7'的所有地方使用nbas。它应该是

i <= 7;

并确保在模拟中测试足够的初始化和不同条件。

© www.soinside.com 2019 - 2024. All rights reserved.