TestBench I2C SDA 不会变低

TestBench I2C SDA won't go low

我正在用 Verilog 编写我的第一个 I2C 程序,但我正在努力使用 TestBench。

我想单独测试 I2C 从设备,但我无法设置不同的 SDA 值:SDA 始终为 1 或 X。

我要用错误的方式进行测试吗?我的想法是我应该能够在每个时钟上设置 SDA,然后看看会发生什么。

游乐场在这里:https://edaplayground.com/x/6snM

module Slave(
    inout SDA,
    input SCL);

  reg [4:0] IDLE        = 4'b0000;
  reg [4:0] START       = 4'b0001;
  reg [4:0] ADDRESS     = 4'b0010;
  reg [4:0] READ_WRITE  = 4'b0011;
  reg [4:0] DATA        = 4'b0100;
  reg [4:0] WRITE_ACK   = 4'b0101;
  reg [4:0] STOP        = 4'b0110;

  reg [4:0] state       = 4'b0000;

  reg [6:0] slaveAddress = 7'b0001000;
  reg [6:0] addressCounter = 7'b0000000;

  reg readWrite         = 1'b0;

  reg write_ack         = 0;

  assign SDA  = write_ack ? 0 : 1'bz;

  always @(posedge SCL)
    begin
      case (state)
        IDLE:
          begin
            if (SDA == 0 && SCL == 1)
            begin
                state <= ADDRESS;
            end
          end
        START: 
          begin
            readWrite <= 0;
          end
        ADDRESS: 
          begin
            if (slaveAddress[addressCounter] != SDA)
            begin
              state <= STOP;
              addressCounter <= 0;
            end

            addressCounter <= addressCounter + 1;
      
            if (addressCounter >= 6) 
                begin
                  write_ack <= 1;
                  state <= READ_WRITE;
                end
          end
        READ_WRITE:
          begin
            write_ack <= 0;
            state <= DATA;
          end
      endcase
    end

endmodule

我想驱动 SDA 以便我可以传递一个位序列,但无论我做什么,SDA 都保持不变 (1) 或 X。

module Slave_TB ();

  reg clk;

  wire SDA;
  wire SCL;

  pullup(SDA);
  pullup(SCL);

  reg [8:0] bitsToSend = 9'b000100010;

  integer ii=0;

  initial begin
        clk = 0;
        forever begin
            clk = #1 ~clk;
        end     
    end


  Slave UUT
    (.SDA(SDA),
     .SCL(SCL));

  initial 
    begin
      $display("Starting Testbench...");
  
      clk = 0;
      force SCL = clk;
  
      #10

      for(ii=0; ii<9; ii=ii+1)
        $display("SDA %h to %h", SDA, bitsToSend[ii]);
        #1 force SDA = bitsToSend[ii];

      #10;
      $finish();
    end

  initial 
  begin
    // Required to dump signals to EPWave
    $dumpfile("dump.vcd");
    $dumpvars(0);
  end

endmodule

我在 $display 语句中添加了 $time,这清楚地表明 SDA 正在发生变化,但它同时发生变化 (10):

              10 SDA 1 to 0
              10 SDA 1 to 1
              10 SDA 1 to 0
              10 SDA 1 to 0
              10 SDA 1 to 0
              10 SDA 1 to 1
              10 SDA 1 to 0
              10 SDA 1 to 0
              10 SDA 1 to 0

您对 for 循环的缩进具有误导性,因为 #1 延迟不是循环的一部分。您需要添加 begin/end 关键字以在 for 循环中包含延迟:

  for(ii=0; ii<9; ii=ii+1) begin
    $display($time, " SDA %h to %h", SDA, bitsToSend[ii]);
    #1 force SDA = bitsToSend[ii];
  end

当我进行更改时,我看到 SDA 波形变低。这是新的打印输出:

              10 SDA 1 to 0
              11 SDA 0 to 1
              12 SDA 1 to 0
              13 SDA 0 to 0
              14 SDA 0 to 0
              15 SDA 0 to 1
              16 SDA 1 to 0
              17 SDA 0 to 0
              18 SDA 0 to 0